diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 8d1f17b3fc..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -# EditorConfig exists: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -[*] -end_of_line = lf -insert_final_newline = true - -charset = utf-8 - -indent_style = space -indent_size = 2 diff --git a/.gitattributes b/.gitattributes index d179a42867..8af4275cc0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,4 +2,4 @@ * text=auto builds/* -text -index.html -text +misc/index.html -text diff --git a/.gitignore b/.gitignore index 12748f8d4f..6e7d8b33ab 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ node_modules/ /dist/ /builds/*.gz /test/ +.editorconfig +.travis.yml +cspell.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 031fe3a6af..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -dist: xenial -language: generic -install: npm install -script: make -branches: - only: - - master diff --git a/Makefile b/Makefile index 01f95ce95b..25aea3d8b5 100644 --- a/Makefile +++ b/Makefile @@ -1,336 +1,44 @@ -ifdef ComSpec - BIN := $(subst /,\,node_modules/.bin/) - RMDIR := -rmdir /s /q - RM := -del - CAT = type $(subst /,\,$1) > $(subst /,\,$2) 2>NUL - MKDIR = -mkdir $(subst /,\,$@) - QUOTE = $(patsubst %,"%",$1) -else - BIN := node_modules/.bin/ - RMDIR := rm -rf - RM := rm -rf - CAT = cat $1 > $2 - MKDIR = mkdir -p $@ - QUOTE = $(patsubst %,'%',$1) -endif -CP = $(call CAT,$<,$@) +.PHONY: update clean hardclean build script chromium stable -npgoals := clean cleanrel cleanweb cleanfull withtests archives $(foreach i,1 2 3 4,bump$(i)) tag tagcommit beta stable web update updatehard -ifneq "$(filter $(npgoals),$(MAKECMDGOALS))" "" -.NOTPARALLEL : -endif - -coffee := $(BIN)coffee -c --no-header -template := node tools/template.js -template_deps := package.json tools/template.js - -# read name meta_name meta_distBranch -$(eval $(shell node tools/pkgvars.js)) - -# must be read in when needed to prevent out-of-date version -version = $(shell node -p "JSON.parse(require('fs').readFileSync('version.json')).version") - -source_directories := \ - globals config css platform classes site \ - Archive Filtering General Images Linkification \ - Menu Miscellaneous Monitoring Posting Quotelinks \ - main - -# remove extension when sorting so X.coffee comes before X.Y.coffee -sort_directory = \ - $(subst !c,.coffee,$(subst !j,.js,$(sort $(subst .coffee,!c,$(subst .js,!j, \ - $(wildcard src/$1/*.coffee src/$1/*.js)))))) - -sources := $(foreach d,$(source_directories),$(call sort_directory,$(d))) - -uses_tests_enabled := \ - src/classes/Post.coffee \ - src/General/Test.coffee \ - src/Linkification/Linkify.coffee \ - src/main/Main.coffee - -imports_src/globals/globals.js := \ - version.json -imports_src/css/CSS.js := \ - node_modules/font-awesome/fonts/fontawesome-webfont.woff -imports_src/Monitoring/Favicon.coffee := \ - src/meta/icon128.png - -imports = \ - $(filter-out %.coffee %.js,$(wildcard $(dir $1)*.*)) \ - $(wildcard $(basename $1)/*.*) \ - $(if $(filter $(uses_tests_enabled),$1),.tests_enabled) \ - $(imports_$1) - -dests_platform = $(addprefix tmp/,$(subst /,-,$(patsubst src/%,%.js,$(subst platform,platform_$2,$1)))) - -dests_of = $(sort $(call dests_platform,$1,crx) $(call dests_platform,$1,userscript)) - -dests := $(foreach s,$(sources),$(call dests_of,$(s))) - -updates := $(subst tmp/,.events/,$(dests)) - -pieces = \ - tmp/LICENSE \ - tmp/meta-newline.js \ - tmp/meta-fbegin.js \ - tmp/meta-newline.js \ - tmp/declaration.js \ - tmp/meta-newline.js \ - $(foreach s,$(sources),$(call dests_platform,$(s),$1)) \ - tmp/meta-fend.js - -crx_contents := script.js eventPage.js icon16.png icon48.png icon128.png manifest.json - -release := \ - $(foreach f, \ - $(foreach c,. -beta.,$(name)$(c)crx updates$(c)xml updates$(c)json $(name)$(c)user.js $(name)$(c)meta.js) \ - $(name)-noupdate.crx \ - $(name)-noupdate.user.js \ - $(name).zip \ - ,builds/$(f)) - -script := $(foreach f,$(filter-out %.crx %.zip,$(release)),test$(f)) $(foreach t,crx crx-beta crx-noupdate,$(foreach f,$(crx_contents),testbuilds/$(t)/$(f))) - -crx := $(foreach f,$(filter %.crx %.zip,$(release)),test$(f)) - -default : script jshint install - -all : default release - -.events .events2 tmp testbuilds builds : - $(MKDIR) - -.tests_enabled : - echo false> .tests_enabled - -.events/declare : $(wildcard src/*/*.coffee) tools/declare.js | .events tmp - node tools/declare.js - echo -> $@ - -tmp/declaration.js : .events/declare - $(if $(wildcard $@),,node tools/declare.js && echo -> $<) - -define check_source -$$(subst tmp/,.events/,$(call dests_of,$1)) : $1 $$(call imports,$1) | .events - echo -> $$(call QUOTE,$$@) -endef - -$(foreach s,$(sources),$(eval $(call check_source,$(subst $$,$$$$,$(s))))) - -.events/compile : $(updates) $(template_deps) tools/chain.js - node tools/chain.js $(call QUOTE, \ - $(subst .events/,tmp/, \ - $(if $(filter-out $(updates),$?), \ - $(updates), \ - $(filter $(updates),$?) \ - ) \ - ) \ - ) - echo -> $@ - -$(dests) : .events/compile - $(if $(wildcard $@),, \ - node tools/chain.js $(call QUOTE, $(filter-out $(wildcard $(dests)),$(dests))) \ - && echo -> $< \ - ) - -tmp/eventPage.js : src/meta/eventPage.coffee | tmp - $(coffee) -o tmp src/meta/eventPage.coffee - -tmp/LICENSE : LICENSE tools/newlinefix.js | tmp - node tools/newlinefix.js $< $@ - -tmp/meta-%.js : src/meta/%.js tools/newlinefix.js | tmp - node tools/newlinefix.js $< $@ - -define rules_channel - -testbuilds/crx$1 : - $$(MKDIR) - -testbuilds/crx$1/script.js : $$(call pieces,crx) | testbuilds/crx$1 .events/compile - @echo Concatenating: $$@ - @$$(call CAT,$$(call QUOTE,$$(call pieces,crx)),$$@) - -testbuilds/crx$1/eventPage.js : tmp/eventPage.js | testbuilds/crx$1 - $$(CP) - -testbuilds/crx$1/icon%.png : src/meta/icon%.png | testbuilds/crx$1 - $$(CP) - -testbuilds/crx$1/manifest.json : src/meta/manifest.json version.json $(template_deps) | testbuilds/crx$1 - $(template) $$< $$@ type=crx channel=$1 - -testbuilds/updates$1.xml : src/meta/updates.xml version.json $(template_deps) | testbuilds/crx$1 - $(template) $$< $$@ type=crx channel=$1 - -testbuilds/updates$1.json : src/meta/updates.json version.json $(template_deps) | testbuilds/crx$1 - $(template) $$< $$@ type=crx channel=$1 - -testbuilds/$(name)$1.crx.zip : \ - $(foreach f,$(crx_contents),testbuilds/crx$1/$(f)) \ - package.json version.json tools/zip-crx.js - node tools/zip-crx.js $1 - -testbuilds/$(name)$1.crx : $(foreach f,$(crx_contents),testbuilds/crx$1/$(f)) version.json tools/sign.sh | tmp - tools/sign.sh $1 - -testbuilds/$(name)$1.meta.js : src/meta/metadata.js src/meta/icon48.png version.json src/Archive/archives.json $(template_deps) | testbuilds - $(template) $$< $$@ type=userscript channel=$1 - -testbuilds/$(name)$1.user.js : testbuilds/$(name)$1.meta.js tmp/meta-newline.js $$(call pieces,userscript) | .events/compile - @echo Concatenating: $$@ - @$$(call CAT,testbuilds/$(name)$1.meta.js tmp/meta-newline.js $$(call QUOTE,$$(call pieces,userscript)),$$@) - -endef - -$(eval $(call rules_channel,)) -$(eval $(call rules_channel,-beta)) -$(eval $(call rules_channel,-noupdate)) - -testbuilds/$(name).zip : testbuilds/$(name)-noupdate.crx.zip - $(CP) - -builds/% : testbuilds/% | builds - $(CP) - -test.html : README.md template.jst tools/markdown.js - node tools/markdown.js - -index.html : test.html - $(CP) - -tmp/.jshintrc : src/meta/jshint.json tmp/declaration.js src/globals/globals.js $(template_deps) | tmp - $(template) $< $@ - -.events/jshint : $(dests) tmp/.jshintrc - $(BIN)jshint $(call QUOTE, \ - $(if $(filter-out $(dests),$?), \ - $(dests), \ - $(filter $(dests),$?) \ - ) \ - ) - echo -> $@ - -install.json : - echo {}> $@ - -.events/install : $(script) install.json tools/install.js | .events - node tools/install.js - echo -> $@ - -.events/CHANGELOG : version.json | .events - node tools/updcl.js - echo -> $@ - -dist : - git worktree add $@ $(meta_distBranch) - -$(wildcard dist/* dist/*/*) : dist - @ - -distready : dist $(wildcard dist/* dist/*/*) - cd dist && git checkout $(meta_distBranch) - cd dist && git pull - -.events2/push-git : .git/refs/heads .git/refs/tags $(wildcard .git/refs/heads/* .git/refs/tags/*) | .events2 distready - git push origin --tags -f - git push origin --all - echo -> $@ - -.events2/push-web : .git/refs/heads/$(meta_distBranch) | .events2 distready - git push web --tags -f - git push web $(meta_distBranch) - echo -> $@ - -.events2/push-store : .git/refs/tags/stable | .events2 distready - node tools/webstore.js - echo -> $@ - -.SECONDARY : - -.PHONY: default all distready script crx release jshint install push $(npgoals) - -script : $(script) - -crx : $(crx) - -release : $(release) - -jshint : .events/jshint - -install : .events/install - -push : .events2/push-git .events2/push-web .events2/push-store - -clean : - $(RMDIR) tmp tmp-crx testbuilds .events - $(RM) .tests_enabled - -cleanrel : clean - $(RMDIR) builds - -cleanweb : - $(RM) test.html - -cleanfull : clean cleanweb - $(RMDIR) .events2 dist node_modules - git worktree prune - -withtests : - echo true> .tests_enabled - -$(MAKE) - echo false> .tests_enabled - -archives : - git fetch -n archives - git merge --no-commit -s ours archives/gh-pages - git show archives/gh-pages:archives.json > src/Archive/archives.json - -git commit -am 'Update archive list.' - -$(foreach i,1 2 3 4,bump$(i)) : - $(MAKE) archives - node tools/bump.js $(subst bump,,$@) - $(MAKE) .events/CHANGELOG - $(MAKE) all - -tag : - git add builds - $(MAKE) cleanrel - $(MAKE) all - git diff --quiet -- builds - $(MAKE) tagcommit - -tagcommit : - git commit -am "Release $(meta_name) v$(version)." - git tag -a $(version) -m "$(meta_name) v$(version)." - -beta : distready - git tag -af beta -m "$(meta_name) v$(version)." - cd dist && git merge --no-commit -s ours beta - cd dist && git checkout beta "builds/*-beta.*" img .gitignore .gitattributes - cd dist && git commit -am "Move $(meta_name) v$(version) to beta channel." - -stable : distready - git push . HEAD:bstable - git tag -af stable -m "$(meta_name) v$(version)." - cd dist && git merge --no-commit -s ours stable - cd dist && git checkout stable "builds/$(name).*" builds/updates.xml builds/updates.json - cd dist && git commit -am "Move $(meta_name) v$(version) to stable channel." - -web : index.html distready - -git commit -am "Build web page." - cd dist && git merge --no-commit -s ours master - cd dist && git checkout master README.md index.html web.css img .gitignore .gitattributes - cd dist && git commit -am "Update web page." - -update : - $(RM) package-lock.json +# Updates npm packages +update: + @echo "Updating the repository..." npm install --save-dev $(shell node tools/unpinned.js) npm install - -updatehard : - $(RM) package-lock.json - npm install --save-dev $(shell node tools/unpinned.js latest) - npm install + @echo "Done." + +# Clean. remove beta-build files and tmp files +clean: + @echo "Cleaning the repository..." + rm -rf tmp tmp-crx testbuilds .events builds/test .test_enabled + +# Runs clean and removes node_modules. Essentially like a fresh install +hardclean: clean + @echo "Hard cleaning the repository..." + rm -rf node_modules + @echo "Done." + +# Builds both the user script and the Chromium extension +build: + @echo "Building the user script..." + npm run build + @echo "Done." + +# This builds only the user script +script: + @echo "Building the user script..." + npm run build:script + @echo "Done." + +# This builds only the Chromium extension +chromium: + @echo "Building the Chromium extension..." + npm run build:crx + @echo "Done." + +# This is more of a dev command as it moves the built files to the releases folder. It also builds them before moving them +stable: build + tools/makeChromium.sh + +# Default target +.DEFAULT_GOAL := build diff --git a/builds/4chan-X-beta.crx b/builds/4chan-X-beta.crx deleted file mode 100644 index 1439282ab5..0000000000 Binary files a/builds/4chan-X-beta.crx and /dev/null differ diff --git a/builds/4chan-X-beta.user.js b/builds/4chan-X-beta.user.js deleted file mode 100644 index 37d9c5c407..0000000000 --- a/builds/4chan-X-beta.user.js +++ /dev/null @@ -1,27999 +0,0 @@ -// ==UserScript== -// @name 4chan X beta -// @version 1.14.22.4 -// @minGMVer 1.14 -// @minFFVer 26 -// @namespace 4chan-X -// @description 4chan X is a script that adds various features to anonymous imageboards. -// @license MIT; https://github.com/ccd0/4chan-x/blob/master/LICENSE -// @include http://boards.4chan.org/* -// @include https://boards.4chan.org/* -// @include http://sys.4chan.org/* -// @include https://sys.4chan.org/* -// @include http://www.4chan.org/* -// @include https://www.4chan.org/* -// @include http://boards.4channel.org/* -// @include https://boards.4channel.org/* -// @include http://sys.4channel.org/* -// @include https://sys.4channel.org/* -// @include http://www.4channel.org/* -// @include https://www.4channel.org/* -// @include http://i.4cdn.org/* -// @include https://i.4cdn.org/* -// @include http://is.4chan.org/* -// @include https://is.4chan.org/* -// @include http://is2.4chan.org/* -// @include https://is2.4chan.org/* -// @include http://is.4channel.org/* -// @include https://is.4channel.org/* -// @include http://is2.4channel.org/* -// @include https://is2.4channel.org/* -// @include https://erischan.org/* -// @include https://www.erischan.org/* -// @include https://fufufu.moe/* -// @include https://gnfos.com/* -// @include https://himasugi.blog/* -// @include https://www.himasugi.blog/* -// @include https://kakashinenpo.com/* -// @include https://www.kakashinenpo.com/* -// @include https://kissu.moe/* -// @include https://www.kissu.moe/* -// @include https://lainchan.org/* -// @include https://www.lainchan.org/* -// @include https://merorin.com/* -// @include https://ota-ch.com/* -// @include https://www.ota-ch.com/* -// @include https://ponyville.us/* -// @include https://www.ponyville.us/* -// @include https://smuglo.li/* -// @include https://notso.smuglo.li/* -// @include https://smugloli.net/* -// @include https://smug.nepu.moe/* -// @include https://sportschan.org/* -// @include https://www.sportschan.org/* -// @include https://sushigirl.us/* -// @include https://www.sushigirl.us/* -// @include https://tvch.moe/* -// @exclude http://www.4chan.org/advertise -// @exclude https://www.4chan.org/advertise -// @exclude http://www.4chan.org/advertise?* -// @exclude https://www.4chan.org/advertise?* -// @exclude http://www.4chan.org/donate -// @exclude https://www.4chan.org/donate -// @exclude http://www.4chan.org/donate?* -// @exclude https://www.4chan.org/donate?* -// @exclude http://www.4channel.org/advertise -// @exclude https://www.4channel.org/advertise -// @exclude http://www.4channel.org/advertise?* -// @exclude https://www.4channel.org/advertise?* -// @exclude http://www.4channel.org/donate -// @exclude https://www.4channel.org/donate -// @exclude http://www.4channel.org/donate?* -// @exclude https://www.4channel.org/donate?* -// @connect 4chan.org -// @connect 4channel.org -// @connect 4cdn.org -// @connect 4chenz.github.io -// @connect archive.4plebs.org -// @connect warosu.org -// @connect desuarchive.org -// @connect boards.fireden.net -// @connect arch.b4k.co -// @connect archived.moe -// @connect thebarchive.com -// @connect archiveofsins.com -// @connect www.tokyochronos.net -// @connect archive.palanq.win -// @connect eientei.xyz -// @connect api.clyp.it -// @connect api.dailymotion.com -// @connect api.github.com -// @connect soundcloud.com -// @connect api.streamable.com -// @connect vimeo.com -// @connect www.youtube.com -// @connect * -// @grant GM_getValue -// @grant GM_setValue -// @grant GM_deleteValue -// @grant GM_listValues -// @grant GM_addValueChangeListener -// @grant GM_openInTab -// @grant GM_xmlhttpRequest -// @grant GM.getValue -// @grant GM.setValue -// @grant GM.deleteValue -// @grant GM.listValues -// @grant GM.openInTab -// @grant GM.xmlHttpRequest -// @run-at document-start -// @updateURL https://www.4chan-x.net/builds/4chan-X-beta.meta.js -// @downloadURL https://www.4chan-x.net/builds/4chan-X-beta.user.js -// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAF5JREFUeNrtkTESABAQxPD/R6tsE2dUGYUtFJvLDKf93KevHJAjpBorAQWSBIKqFASC4G0pCAkm4GfaEvgYXl0T6HBaE97f0vmnfYHbZOMLZCx9ISdKWwjOWZSC8GYm4SUGwfYgqI4AAAAASUVORK5CYII= -// ==/UserScript== - -/* -* 4chan X -* -* Licensed under the MIT license. -* https://github.com/ccd0/4chan-x/blob/master/LICENSE -* -* Appchan X Copyright © 2013-2016 Zixaphir -* http://zixaphir.github.io/appchan-x/ -* 4chan x Copyright © 2009-2011 James Campos -* https://github.com/aeosynth/4chan-x -* 4chan x Copyright © 2012-2014 Nicolas Stepien -* https://4chan-x.just-believe.in/ -* 4chan x Copyright © 2013-2014 Jordan Bates -* http://seaweedchan.github.io/4chan-x/ -* 4chan x Copyright © 2012-2013 ihavenoface -* http://ihavenoface.github.io/4chan-x/ -* 4chan SS Copyright © 2011-2013 Ahodesuka -* https://github.com/ahodesuka/4chan-Style-Script/ -* -* 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 -* detharonil -* -* All the people who've taken the time to write bug reports. -* -* Thank you. -*/ - -/* -* Contains data from external sources: -* -* src/Monitoring/ThreadUpdater/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ -* cc-by-nc-3.0 -* -* Font Awesome by Dave Gandy (http://fontawesome.io) -* license: http://fontawesome.io/license/ -* -* Icons used to identify various websites are property of the respective websites. -*/ - -(function() { - -'use strict'; - -var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, BoardConfig, CSS, Callbacks, Captcha, CatalogLinks, CatalogThread, CatalogThreadNative, Config, Connection, CopyTextLink, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, IDPostCount, ImageCommon, ImageExpand, ImageHost, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, ModContact, Nav, NormalizeURL, Notice, PSA, PSAHiding, PassLink, PassMessage, Polyfill, Post, PostHiding, PostJumper, PostRedirect, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, SW, Sauce, Settings, ShimSet, SimpleDict, Site, Test, Thread, ThreadHiding, ThreadLinks, ThreadStats, ThreadUpdater, ThreadWatcher, Time, Tinyboard, UI, Unread, UnreadIndex, Volume; - -var Conf, E, c, d, doc, docSet, g; - -Conf = Object.create(null); -c = console; -d = document; -doc = d.documentElement; - -// Workaround for userscript managers that run script before document.documentElement is set -docSet = function() { - return (doc = d.documentElement); -}; - -g = { - VERSION: '1.14.22.4', - NAMESPACE: '4chan X.', - sites: Object.create(null), - boards: Object.create(null) -}; - -E = (function() { - var fn, r, regex, str; - str = { - '&': '&', - "'": ''', - '"': '"', - '<': '<', - '>': '>' - }; - r = String.prototype.replace; - regex = /[&"'<>]/g; - fn = function(x) { - return str[x]; - }; - return function(text) { - return r.call(text, regex, fn); - }; -})(); - -E.cat = function(templates) { - var html, i, len; - html = ''; - for (i = 0, len = templates.length; i < len; i++) { - html += templates[i].innerHTML; - } - return html; -}; - -Config = (function() { - var Config; - - Config = { - main: { - 'Miscellaneous': { - 'Redirect to HTTPS': [true, 'Redirect to the HTTPS version of 4chan.'], - 'JSON Index': [true, 'Replace the original board index with one supporting searching, sorting, infinite scrolling, and a catalog mode.'], - 'Use 4chan X Catalog': [true, 'Link to 4chan X\'s catalog instead of the native 4chan one.', 1], - 'Index Refresh Notifications': [false, 'Show a notice at the top of the page when the index is refreshed.', 1], - 'Follow Cursor': [true, 'Image Hover and Quote Preview move with the mouse cursor.'], - 'Open Threads in New Tab': [false, 'Make links to threads in the index / 4chan X catalog open in a new tab.'], - 'External Catalog': [false, 'Link to external catalog instead of the internal one.'], - 'Catalog Links': [false, 'Add toggle link in header menu to turn Navigation links into links to each board\'s catalog.'], - 'Announcement Hiding': [true, 'Add button to hide 4chan announcements.'], - 'Desktop Notifications': [true, 'Enables desktop notifications across various 4chan X features.'], - '404 Redirect': [true, 'Redirect dead threads and images to the archives.'], - 'Archive Report': [true, 'Enable reporting posts to supported archives.'], - 'Exempt Archives from Encryption': [true, 'Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages.'], - 'Keybinds': [true, 'Bind actions to keyboard shortcuts.'], - 'Time Formatting': [true, 'Localize and format timestamps.'], - 'Relative Post Dates': [true, 'Display dates like "3 minutes ago". Tooltip shows the timestamp.'], - 'Relative Date Title': [true, 'Show Relative Post Date only when hovering over dates.', 1], - 'Comment Expansion': [true, 'Expand comments that are too long to display on the index. Not applicable with JSON Index.'], - 'File Info Formatting': [true, 'Reformat the file information.'], - 'Thread Expansion': [true, 'Add buttons to expand threads.'], - 'Index Navigation': [false, 'Add buttons to navigate between threads.'], - 'Reply Navigation': [false, 'Add buttons to navigate to top / bottom of thread.'], - 'Unique ID and Capcode Navigation': [false, 'Add buttons to navigate to posts having the same unique ID or capcode.'], - 'Custom Board Titles': [true, 'Allow editing of the board title and subtitle by ctrl/\u2318+clicking them.'], - 'Persistent Custom Board Titles': [false, 'Force custom board titles to be persistent, even if the board titles are updated.', 1], - 'Show Updated Notifications': [true, 'Show notifications when 4chan X is successfully updated.'], - 'Color User IDs': [true, 'Assign unique colors to user IDs on boards that use them'], - 'Count Posts by ID': [true, 'Display number of posts in the thread when hovering over an ID.'], - 'Remove Spoilers': [false, 'Remove all spoilers in text.'], - 'Reveal Spoilers': [false, 'Indicate spoilers if Remove Spoilers is enabled, or make the text appear hovered if Remove Spoiler is disabled.'], - 'Normalize URL': [true, 'Rewrite the URL of the current page, removing slugs and excess slashes, and changing /res/ to /thread/.'], - 'Work around CORB Bug': [true, 'Leave this checked until your garbage browser is fixed.'], - 'Disable Autoplaying Sounds': [false, 'Prevent sounds on the page from autoplaying.'], - 'Disable Native Extension': [true, '4chan X is NOT designed to work with the native extension.'], - 'Enable Native Flash Embedding': [true, 'Activate the native extension\'s Flash embedding if the native extension is disabled.'] - }, - 'Linkification': { - 'Linkify': [true, 'Convert text into links where applicable.'], - 'Link Title': [true, 'Replace the link of a supported site with its actual title.', 1], - 'Cover Preview': [true, 'Show preview of supported links on hover.', 1], - 'Embedding': [true, 'Embed supported services. Note: Some services don\'t work on HTTPS.', 1], - 'Auto-embed': [false, 'Auto-embed Linkify Embeds.', 2], - 'Floating Embeds': [false, 'Embed content in a frame that remains in place when the page is scrolled.', 2] - }, - 'Filtering': { - 'Anonymize': [false, 'Make everyone Anonymous.'], - 'Filter': [true, 'Self-moderation placebo.'], - 'Filtered Backlinks': [false, 'When enabled, shows backlinks to filtered posts with a line-through decoration. Otherwise, hides the backlinks.', 1], - 'Filter in Native Catalog': [true, 'Apply 4chan X filters in native catalog.', 1], - 'MD5 Quick Filter Notifications': [true, 'Show notification when quick filtering MD5s using the button or keybind.', 1], - 'Recursive Hiding': [true, 'Hide replies of hidden posts, recursively.'], - 'Thread Hiding Buttons': [true, 'Add buttons to hide entire threads.'], - 'Reply Hiding Buttons': [true, 'Add buttons to hide single replies.'], - 'Stubs': [true, 'Show stubs of hidden threads / replies.'] - }, - 'Images and Videos': { - 'Image Expansion': [true, 'Expand images / videos.'], - 'Image Hover': [true, 'Show full image / video on mouseover.'], - 'Image Hover in Catalog': [true, 'Show full image / video on mouseover in 4chan X catalog.'], - 'Gallery': [true, 'Adds a simple and cute image gallery. Has more options in the gallery menu.'], - 'Fullscreen Gallery': [false, 'Open gallery in fullscreen mode.', 1], - 'PDF in Gallery': [false, 'Show PDF files in gallery.', 1], - 'Sauce': [true, 'Add sauce links to images.'], - 'WEBM Metadata': [true, 'Add link to fetch title metadata from webm videos.'], - 'Reveal Spoiler Thumbnails': [false, 'Replace spoiler thumbnails with the original image.'], - 'Replace GIF': [false, 'Replace gif thumbnails with the actual image.'], - 'Replace JPG': [false, 'Replace jpg thumbnails with the actual image.'], - 'Replace PNG': [false, 'Replace png thumbnails with the actual image.'], - 'Replace WEBM': [false, 'Replace webm, mp4, and ogv thumbnails with the actual video. Probably will degrade browser performance ;)'], - 'Image Prefetching': [true, 'Add a shortcut icon to the header to turn on image preloading.'], - 'Fappe Tyme': [true, 'Hide posts without images when header menu item is checked. *hint* *hint*'], - 'Werk Tyme': [true, 'Hide all post images when header menu item is checked.'], - 'Autoplay': [true, 'Videos begin playing immediately when opened.'], - 'Restart when Opened': [false, 'Restart GIFs and WebMs when you hover over or expand them.'], - 'Show Controls': [true, 'Show controls on videos expanded inline.'], - 'Click Passthrough': [false, 'Clicks on videos trigger your browser\'s default behavior. Videos can be contracted with button / dragging to the left.', 1], - 'Allow Sound': [true, 'Open videos with the sound unmuted.'], - 'Mouse Wheel Volume': [true, 'Adjust volume of videos with the mouse wheel over the thumbnail/filename/gallery.'], - 'Loop in New Tab': [true, 'Loop videos opened in their own tabs.'], - 'Volume in New Tab': [true, 'Apply 4chan X mute and volume settings to videos opened in their own tabs.'] - }, - 'Menu': { - 'Menu': [true, 'Add a drop-down menu to posts.'], - 'Report Link': [true, 'Add a report link to the menu.', 1], - 'Copy Text Link': [true, 'Add a link to copy the post\'s text.', 1], - 'Thread Hiding Link': [true, 'Add a link to hide entire threads.', 1], - 'Reply Hiding Link': [true, 'Add a link to hide single replies.', 1], - 'Delete Link': [true, 'Add post and image deletion links to the menu.', 1], - 'Archive Link': [true, 'Add an archive link to the menu.', 1], - 'Edit Link': [true, 'Add a link to edit the image in Tegaki, /i/\'s painting program. Requires Quick Reply.', 1], - 'Download Link': [false, 'Add a download with original filename link to the menu.', 1] - }, - 'Monitoring': { - 'Thread Updater': [true, 'Fetch and insert new replies. Has more options in the header menu and the "Advanced" tab.'], - 'Unread Count': [true, 'Show the unread posts count in the tab title.'], - 'Quoted Title': [false, 'Change the page title to reflect you\'ve been quoted.', 1], - 'Hide Unread Count at (0)': [false, 'Hide the unread posts count in the tab title when it reaches 0.', 1], - 'Unread Favicon': [true, 'Show a different favicon when there are unread posts.'], - 'Unread Line': [true, 'Show a line to distinguish read posts from unread ones.'], - 'Remember Last Read Post': [true, 'Remember how far you\'ve read after you close the thread.'], - 'Scroll to Last Read Post': [true, 'Scroll back to the last read post when reopening a thread.', 1], - 'Unread Line in Index': [false, 'Show a line between read and unread posts in threads in the index.', 1], - 'Remove Thread Excerpt': [false, 'Replace the excerpt of the thread in the tab title with the board title.'], - 'Thread Stats': [true, 'Display reply and image count.'], - 'IP Count in Stats': [true, 'Display the unique IP count in the thread stats.', 1], - 'Page Count in Stats': [true, 'Display the page count in the thread stats.', 1], - 'Updater and Stats in Header': [true, 'Places the thread updater and thread stats in the header instead of floating them.'], - 'Thread Watcher': [true, 'Bookmark threads. Has more options in the thread watcher menu.'], - 'Fixed Thread Watcher': [true, 'Makes the thread watcher scroll with the page.', 1], - 'Persistent Thread Watcher': [false, 'The thread watcher will be visible when the page is loaded.', 1], - 'Mark New IPs': [false, 'Label each post from a new IP with the thread\'s current IP count.'], - 'Reply Pruning': [true, 'Add option in header menu to hide old replies in long threads. Activated by default in stickies.'], - 'Prune All Threads': [false, 'Activate Reply Pruning by default in all threads.', 1] - }, - 'Posting and Captchas': { - 'Quick Reply': [true, 'All-in-one form to reply, create threads, automate dumping and more.'], - 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.', 1], - 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.', 2], - 'Open Post in New Tab': [true, 'Open new threads in a new tab, and open replies in a new tab if you\'re not already in the thread.', 1], - 'Remember QR Size': [false, 'Remember the size of the Quick reply.', 1], - 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.', 1], - 'Randomize Filename': [false, 'Set the filename to a random timestamp within the past year. Disabled on /f/.', 1], - 'Show New Thread Option in Threads': [true, 'Show the option to post a new / different thread from inside a thread.', 1], - 'Show Upload Progress': [true, 'Track progress of file uploads as percentage in submit button.', 1], - 'Cooldown': [true, 'Indicate the remaining time before posting again.', 1], - 'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1], - 'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1], - 'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1], - 'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha even if Javascript is enabled.'], - 'Pass Link': [false, 'Add a 4chan Pass login link to the bottom of the page.'] - }, - 'Quote Links': { - 'Quote Backlinks': [true, 'Add quote backlinks.'], - 'OP Backlinks': [true, 'Add backlinks to the OP.', 1], - 'Bottom Backlinks': [false, 'Place backlinks at the bottom of posts.', 1], - 'Quote Inlining': [true, 'Inline quoted post on click.'], - 'Inline Cross-thread Quotes Only': [false, 'Don\'t inline quote links when the posts are visible in the thread.', 1], - 'Quote Hash Navigation': [false, 'Include an extra link after quotes for autoscrolling to quoted posts.', 1], - 'Forward Hiding': [true, 'Hide original posts of inlined backlinks.', 1], - 'Quote Previewing': [true, 'Show quoted post on hover.'], - 'Quote Highlighting': [true, 'Highlight the previewed post.', 1], - 'Resurrect Quotes': [true, 'Link dead quotes to the archives, and support inlining/previewing of archive links like quote links.'], - 'Remember Your Posts': [true, 'Remember your posting history.'], - 'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.', 1], - 'Highlight Posts Quoting You': [true, 'Highlights any posts that contain a quote to your post.', 1], - 'Highlight Own Posts': [true, 'Highlights own posts.', 1], - 'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'], - 'Mark Cross-thread Quotes': [true, 'Add \'(Cross-thread)\' to cross-threads quotes.'], - 'Quote Threading': [true, 'Add option in header menu to thread conversations.'] - } - }, - imageExpansion: { - 'Fit width': [true, ''], - 'Fit height': [false, ''], - 'Scroll into view': [true, 'Scroll down when expanding images to bring the full image into view.'], - 'Expand spoilers': [true, 'Expand all images along with spoilers.'], - 'Expand videos': [true, 'Expand all images also expands videos.'], - 'Expand from here': [false, 'Expand all images only from current position to thread end.'], - 'Expand thread only': [false, 'In index, expand all images only within the current thread.'], - 'Advance on contract': [false, 'Advance to next post when contracting an expanded image.'] - }, - gallery: { - 'Hide Thumbnails': [false], - 'Fit Width': [true], - 'Fit Height': [true], - 'Stretch to Fit': [false], - 'Scroll to Post': [true], - 'Slide Delay': [6.0] - }, - 'Default Volume': 1.0, - threadWatcher: { - 'Current Board': [false, 'Only show watched threads from the current board.'], - 'Auto Update Thread Watcher': [true, 'Periodically check status of watched threads.'], - 'Auto Watch': [true, 'Automatically watch threads you start.'], - 'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'], - 'Auto Prune': [false, 'Automatically remove dead threads.'], - 'Show Page': [true, 'Show what page watched threads are on.'], - 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'], - 'Show Site Prefix': [true, 'When multiple sites are shown in the thread watcher, add a prefix to board names to distinguish them.'], - 'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.'] - }, - filter: { - general: '', - postID: "# Highlight dubs on [s4s]:\n#/(\\d)\\1$/;highlight;top:no;boards:s4s", - name: "# Filter any namefags:\n#/^(?!Anonymous$)/", - uniqueID: "# Filter a specific ID:\n#/Txhvk1Tl/", - tripcode: "# Filter any tripfag\n#/^!/", - capcode: "# Set a custom class for mods:\n#/Mod$/;highlight:mod;op:yes\n# Set a custom class for admins:\n#/Admin$/;highlight:admin;op:yes", - pass: "# Filter anyone using since4pass:\n#/./", - email: '', - 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\n# Filter posts with 20 or more quote links:\n#/(?:>>\\d(?:(?!>>\\d)[^])*){20}/\n# Filter posts like T H I S / H / I / S:\n#/^>?\\s?\\w\\s?(\\w)\\s?(\\w)\\s?(\\w).*$[\\s>]+\\1[\\s>]+\\2[\\s>]+\\3/im", - flag: '', - filename: '', - dimensions: "# Highlight potential wallpapers:\n#/1920x1080/;op:yes;highlight;top:no;boards:w,wg", - filesize: '', - MD5: '' - }, - sauces: "# Known filename formats:\nhttps://www.pixiv.net/member_illust.php?mode=medium&illust_id=%$1;regexp:/^(\\d+)_p\\d+/\njavascript:void(open(\"https://www.deviantart.com/\"+%$1.replace(/_/g,\"-\")+\"/art/\"+parseInt(%$2,36)));regexp:/^\\w+_by_(\\w+)[_-]d([\\da-z]{6})\\b/\nhttps://imgur.com/%$1;regexp:/^(?![a-zA-Z][a-z]{6})(?![A-Z]{7})(?!\\d{7})([\\da-zA-Z]{7})(?: \\(\\d+\\))?\\.\\w+$/\nhttps://flickr.com/photo.gne?id=%$1;regexp:/^(\\d+)_[\\da-f]{10}(?:_\\w)*\\b/\nhttps://www.facebook.com/photo.php?fbid=%$1;regexp:/^\\d+_(\\d+)_\\d+_[no]\\b/\n\n# Reverse image search:\nhttps://www.google.com/searchbyimage?sbisrc=4chanx&image_url=%IMG&safe=off\nhttps://yandex.com/images/search?rpt=imageview&url=%IMG\n#//tineye.com/search?url=%IMG\n#//www.bing.com/images/search?q=imgurl:%IMG&view=detailv2&iss=sbi#enterInsights\n#https://lens.google.com/uploadbyurl?url=%IMG;text:lens\n\n# Specialized reverse image search:\n//iqdb.org/?url=%IMG\nhttps://trace.moe/?auto&url=%IMG;text:wait\n#//3d.iqdb.org/?url=%IMG\n#//saucenao.com/search.php?url=%IMG\n\n# \"View Same\" in archives:\nhttp://eye.swfchan.com/search/?q=%name;types:swf\n#https://desuarchive.org/_/search/image/%sMD5/\n#https://archive.4plebs.org/_/search/image/%sMD5/\n#https://boards.fireden.net/_/search/image/%sMD5/\n#https://foolz.fireden.net/_/search/image/%sMD5/\n\n# Other tools:\n#http://exif.regex.info/exif.cgi?imgurl=%URL\n#//imgops.com/start?url=%URL;types:gif,jpg,png\n#//www.gif-explode.com/%URL;types:gif", - FappeT: { - werk: false - }, - 'Custom CSS': true, - Index: { - 'Index Mode': 'paged', - 'Previous Index Mode': 'paged', - 'Index Size': 'small', - 'Show Replies': [true, 'Show replies in the index, and also in the catalog if "Catalog hover expand" is checked.'], - 'Catalog Hover Expand': [false, 'Expand the comment and show more details when you hover over a thread in the catalog.'], - 'Catalog Hover Toggle': [true, 'Turn "Catalog hover expand" on and off by clicking in the catalog.'], - 'Pin Watched Threads': [false, 'Move watched threads to the start of the index.'], - 'Anchor Hidden Threads': [true, 'Move hidden threads to the end of the index.'], - 'Refreshed Navigation': [false, 'Refresh index when navigating through pages.'] - }, - Header: { - 'Fixed Header': true, - 'Header auto-hide': false, - 'Header auto-hide on scroll': false, - 'Bottom Header': false, - 'Centered links': false, - 'Header catalog links': false, - 'Bottom Board List': true, - 'Shortcut Icons': true, - 'Custom Board Navigation': true - }, - archives: { - archiveLists: 'https://4chenz.github.io/archives.json/archives.json', - lastarchivecheck: 0, - archiveAutoUpdate: true - }, - externalCatalogURLs: "//catalog.neet.tv/%board/;boards:4chan.org:3,a,adv,an,asp,biz,c,cgl,ck,cm,co,diy,f,fa,fit,g,gd,his,i,int,jp,k,lgbt,lit,m,mlp,mu,n,news,o,out,p,po,pol,s4s,sci,sp,tg,toy,trv,tv,v,vg,vip,vp,vr,w,wg,wsg,wsr,x", - boardnav: "[ toggle-all ]\n[current-index-text:\"Index\"\ncurrent-catalog-text:\"Catalog\"\ncurrent-expired-text:\"Expired\"\ncurrent-archive-text:\"Archive\"]\n[external-text:\"FAQ\",\"https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions\"]", - QR: { - 'QR.personas': "#options:\"sage\";boards:jp;always", - sjisPreview: false - }, - jsWhitelist: 'http://s.4cdn.org\nhttps://s.4cdn.org\nhttp://www.google.com\nhttps://www.google.com\nhttps://www.gstatic.com\nhttp://cdn.mathjax.org\nhttps://cdn.mathjax.org\nhttps://cdnjs.cloudflare.com\nhttps://hcaptcha.com\nhttps://*.hcaptcha.com\n\'self\'\n\'unsafe-inline\'\n\'unsafe-eval\'', - captchaLanguage: '', - time: '%m/%d/%y(%a)%H:%M:%S', - timeLocale: '', - backlink: '>>%id', - pastedname: 'file', - fileInfo: '%l %d (%p%s, %r%g)', - favicon: 'ferongr', - usercss: "/* Board title rice */\ndiv.boardTitle {\n font-weight: 400 !important;\n}\n:root.yotsuba div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(100,0,0,0.6);\n}\n:root.yotsuba-b div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(105,10,15,0.6);\n}\n:root.photon div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(0,74,153,0.6);\n}\n:root.tomorrow div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(167,170,168,0.6);\n}\n", - hotkeys: { - 'Toggle board list': ['Ctrl+b', 'Toggle the full board list.'], - 'Toggle header': ['Shift+h', 'Toggle the auto-hide option of the header.'], - 'Open empty QR': ['q', 'Open QR without post number inserted.'], - 'Open QR': ['Shift+q', 'Open QR with post number inserted.'], - 'Open settings': ['Alt+o', 'Open Settings.'], - 'Close': ['Esc', 'Close dialogs or notifications.'], - 'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.'], - 'Code tags': ['Alt+c', 'Insert code tags.'], - 'Eqn tags': ['Alt+e', 'Insert eqn tags.'], - 'Math tags': ['Alt+m', 'Insert math tags.'], - 'SJIS tags': ['Alt+a', 'Insert SJIS tags.'], - 'Toggle sage': ['Alt+s', 'Toggle sage in options field.'], - 'Toggle Cooldown': ['Alt+Comma', 'Toggle custom cooldown timer.'], - 'Post from URL': ['Alt+l', 'Post from URL.'], - 'Add new post': ['Alt+n', 'Add new post to the QR dump list.'], - 'Submit QR': ['Ctrl+Enter', 'Submit post.'], - 'Watch': ['w', 'Watch thread.'], - 'Update': ['r', 'Update the thread / refresh the index.'], - 'Update thread watcher': ['Shift+r', 'Manually refresh thread watcher.'], - 'Toggle thread watcher': ['t', 'Toggle visibility of thread watcher.'], - 'Toggle threading': ['Shift+t', 'Toggle threading.'], - 'Mark thread read': ['Ctrl+0', 'Mark thread read from index (requires "Unread Line in Index").'], - 'Expand image': ['Shift+e', 'Expand selected image.'], - 'Expand images': ['e', 'Expand all images.'], - 'Open Gallery': ['g', 'Opens the gallery.'], - 'Next Gallery Image': ['Right', 'Go to the next image in gallery mode.'], - 'Previous Gallery Image': ['Left', 'Go to the previous image in gallery mode.'], - 'Advance Gallery': ['Enter', 'Go to next image or, if Autoplay is off, play video.'], - 'Pause': ['p', 'Pause/play videos in the gallery.'], - 'Slideshow': ['Ctrl+Right', 'Toggle the gallery slideshow mode.'], - 'Rotate image clockwise': ['Shift+Right', 'Rotate image clockwise in gallery.'], - 'Rotate image anticlockwise': ['Shift+Left', 'Rotate image anticlockwise in gallery.'], - 'Download Gallery Image': ['Shift+j', 'Download current image in gallery.'], - 'fappeTyme': ['f', 'Toggle Fappe Tyme.'], - 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], - 'Front page': ['1', 'Jump to front page.'], - 'Open front page': ['Shift+1', 'Open front page in a new tab.'], - 'Next page': ['Ctrl+Right', 'Jump to the next page.'], - 'Previous page': ['Ctrl+Left', 'Jump to the previous page.'], - 'Paged mode': ['Alt+1', 'Open the index in paged mode.'], - 'Infinite scrolling mode': ['Alt+2', 'Open the index in infinite scrolling mode.'], - 'All pages mode': ['Alt+3', 'Open the index in all threads mode.'], - 'Open catalog': ['Shift+c', 'Open the catalog of the current board.'], - 'Search form': ['Ctrl+Alt+s', 'Focus the search field on the board index.'], - 'Cycle sort type': ['Alt+x', 'Cycle through index sort types.'], - 'Next thread': ['Ctrl+Down', 'See next thread.'], - 'Previous thread': ['Ctrl+Up', 'See previous thread.'], - 'Expand thread': ['Ctrl+e', 'Expand thread.'], - 'Open thread': ['o', 'Open thread in current tab.'], - 'Open thread tab': ['Shift+o', 'Open thread in new tab.'], - 'Next reply': ['j', 'Select next reply.'], - 'Previous reply': ['k', 'Select previous reply.'], - 'Deselect reply': ['Shift+d', 'Deselect reply.'], - 'Hide': ['x', 'Hide thread.'], - 'Quick Filter MD5': ['5', 'Add the MD5 of the selected image to the filter list.'], - 'Previous Post Quoting You': ['Alt+Up', 'Scroll to the previous post that quotes you.'], - 'Next Post Quoting You': ['Alt+Down', 'Scroll to the next post that quotes you.'] - }, - updater: { - checkbox: { - 'Beep': [false, 'Beep on new post to completely read thread.'], - 'Beep Quoting You': [false, 'Beep on new post quoting you.'], - 'Auto Scroll': [false, 'Scroll updated posts into view. Only enabled at bottom of page.'], - 'Bottom Scroll': [false, 'Always scroll to the bottom, not the first new post. Useful for event threads.'], - 'Scroll BG': [false, 'Auto-scroll background tabs.'], - 'Auto Update': [true, 'Automatically fetch new posts.'], - 'Optional Increase': [false, 'Increase the intervals between updates on threads without new posts.'] - }, - 'Interval': 5 - }, - customCooldown: 0, - customCooldownEnabled: true, - 'Thread Quotes': false, - 'Max Replies': 1000, - 'Autohiding Scrollbar': false, - position: { - 'embedding.position': 'top: 50px; right: 0px;', - 'thread-stats.position': 'bottom: 0px; right: 0px;', - 'updater.position': 'bottom: 0px; left: 0px;', - 'thread-watcher.position': 'top: 50px; left: 0px;', - 'qr.position': 'top: 50px; right: 0px;' - }, - fourchanImageHost: 'i.4cdn.org', - hiddenPSAList: [{}], - knownBanners: '0.jpg,1.jpg,2.jpg,4.jpg,6.jpg,7.jpg,8.jpg,9.jpg,10.jpg,11.jpg,12.jpg,13.jpg,14.jpg,16.jpg,17.jpg,18.jpg,19.jpg,20.jpg,21.jpg,22.jpg,24.jpg,25.jpg,26.jpg,28.jpg,29.jpg,33.jpg,38.jpg,39.jpg,43.jpg,44.jpg,45.jpg,46.jpg,47.jpg,52.jpg,54.jpg,57.jpg,59.jpg,60.jpg,61.jpg,64.jpg,66.jpg,67.jpg,69.jpg,71.jpg,72.jpg,76.jpg,77.jpg,81.jpg,82.jpg,83.jpg,84.jpg,88.jpg,90.jpg,91.jpg,96.jpg,98.jpg,99.jpg,100.jpg,104.jpg,106.jpg,116.jpg,119.jpg,137.jpg,140.jpg,148.jpg,149.jpg,150.jpg,154.jpg,156.jpg,157.jpg,158.jpg,159.jpg,161.jpg,162.jpg,164.jpg,165.jpg,166.jpg,167.jpg,168.jpg,169.jpg,170.jpg,171.jpg,172.jpg,173.jpg,174.jpg,175.jpg,176.jpg,178.jpg,179.jpg,180.jpg,181.jpg,182.jpg,183.jpg,186.jpg,189.jpg,190.jpg,192.jpg,193.jpg,194.jpg,197.jpg,198.jpg,200.jpg,201.jpg,202.jpg,203.jpg,205.jpg,206.jpg,207.jpg,208.jpg,210.jpg,213.jpg,214.jpg,215.jpg,216.jpg,218.jpg,219.jpg,220.jpg,221.jpg,222.jpg,223.jpg,224.jpg,227.jpg,0.png,1.png,2.png,3.png,5.png,6.png,9.png,10.png,11.png,12.png,14.png,16.png,19.png,20.png,21.png,22.png,23.png,24.png,26.png,27.png,28.png,29.png,30.png,31.png,32.png,33.png,34.png,37.png,39.png,40.png,41.png,42.png,43.png,44.png,45.png,48.png,49.png,50.png,51.png,52.png,53.png,57.png,58.png,59.png,64.png,66.png,67.png,68.png,69.png,70.png,71.png,72.png,76.png,78.png,79.png,81.png,82.png,85.png,86.png,87.png,89.png,95.png,98.png,100.png,101.png,102.png,105.png,106.png,107.png,109.png,110.png,111.png,112.png,113.png,114.png,115.png,116.png,118.png,119.png,120.png,121.png,122.png,123.png,126.png,128.png,130.png,134.png,136.png,138.png,139.png,140.png,142.png,145.png,146.png,149.png,150.png,151.png,152.png,153.png,154.png,155.png,156.png,157.png,158.png,159.png,160.png,163.png,164.png,165.png,166.png,167.png,168.png,169.png,170.png,171.png,172.png,173.png,174.png,178.png,179.png,180.png,181.png,182.png,184.png,186.png,188.png,190.png,192.png,193.png,194.png,195.png,196.png,197.png,198.png,200.png,202.png,203.png,205.png,206.png,207.png,209.png,212.png,213.png,214.png,216.png,217.png,218.png,219.png,220.png,221.png,222.png,223.png,224.png,225.png,226.png,229.png,231.png,232.png,233.png,234.png,235.png,237.png,238.png,239.png,240.png,241.png,242.png,244.png,245.png,246.png,247.png,248.png,249.png,250.png,253.png,254.png,255.png,256.png,257.png,258.png,259.png,260.png,262.png,268.png,0.gif,1.gif,2.gif,3.gif,4.gif,5.gif,6.gif,7.gif,8.gif,9.gif,10.gif,12.gif,13.gif,14.gif,15.gif,16.gif,18.gif,19.gif,20.gif,21.gif,22.gif,23.gif,24.gif,28.gif,29.gif,30.gif,33.gif,34.gif,35.gif,36.gif,37.gif,39.gif,40.gif,42.gif,44.gif,45.gif,46.gif,48.gif,50.gif,52.gif,54.gif,55.gif,57.gif,58.gif,59.gif,60.gif,61.gif,63.gif,64.gif,66.gif,67.gif,68.gif,69.gif,70.gif,72.gif,73.gif,75.gif,76.gif,77.gif,78.gif,80.gif,81.gif,82.gif,83.gif,86.gif,87.gif,88.gif,92.gif,93.gif,94.gif,95.gif,96.gif,97.gif,98.gif,99.gif,100.gif,101.gif,102.gif,103.gif,104.gif,105.gif,106.gif,108.gif,109.gif,110.gif,111.gif,112.gif,113.gif,115.gif,116.gif,117.gif,118.gif,119.gif,120.gif,122.gif,123.gif,124.gif,127.gif,129.gif,130.gif,131.gif,134.gif,135.gif,136.gif,138.gif,139.gif,141.gif,144.gif,146.gif,148.gif,149.gif,153.gif,154.gif,155.gif,157.gif,158.gif,159.gif,160.gif,161.gif,162.gif,164.gif,166.gif,167.gif,168.gif,169.gif,170.gif,171.gif,172.gif,173.gif,174.gif,175.gif,176.gif,177.gif,178.gif,181.gif,182.gif,183.gif,185.gif,186.gif,187.gif,188.gif,189.gif,190.gif,191.gif,192.gif,193.gif,195.gif,196.gif,197.gif,200.gif,201.gif,202.gif,203.gif,204.gif,205.gif,206.gif,207.gif,208.gif,209.gif,210.gif,211.gif,212.gif,213.gif,214.gif,215.gif,216.gif,217.gif,219.gif,220.gif,221.gif,222.gif,224.gif,225.gif,226.gif,227.gif,228.gif,230.gif,232.gif,233.gif,234.gif,235.gif,238.gif,240.gif,241.gif,243.gif,244.gif,245.gif,246.gif,247.gif,249.gif,250.gif,251.gif,253.gif', - passMessageClosed: false, - 'Prerequest Captcha': false, - 'PSAseen': [[]] - }; - - return Config; - -}).call(this); - -CSS = { - -boards: -"/*!\n\ - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n\ - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n\ - */\n\ -@font-face {\n\ - font-family: FontAwesome;\n\ - src: url('data:application/font-woff;base64,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') format('woff');\n\ - font-weight: 400;\n\ - font-style: normal;\n\ -}\n\ -.fa-glass:before {content: \"\\f000\";}\n\ -.fa-music:before {content: \"\\f001\";}\n\ -.fa-search:before {content: \"\\f002\";}\n\ -.fa-envelope-o:before {content: \"\\f003\";}\n\ -.fa-heart:before {content: \"\\f004\";}\n\ -.fa-star:before {content: \"\\f005\";}\n\ -.fa-star-o:before {content: \"\\f006\";}\n\ -.fa-user:before {content: \"\\f007\";}\n\ -.fa-film:before {content: \"\\f008\";}\n\ -.fa-th-large:before {content: \"\\f009\";}\n\ -.fa-th:before {content: \"\\f00a\";}\n\ -.fa-th-list:before {content: \"\\f00b\";}\n\ -.fa-check:before {content: \"\\f00c\";}\n\ -.fa-remove:before, .fa-close:before, .fa-times:before {content: \"\\f00d\";}\n\ -.fa-search-plus:before {content: \"\\f00e\";}\n\ -.fa-search-minus:before {content: \"\\f010\";}\n\ -.fa-power-off:before {content: \"\\f011\";}\n\ -.fa-signal:before {content: \"\\f012\";}\n\ -.fa-gear:before, .fa-cog:before {content: \"\\f013\";}\n\ -.fa-trash-o:before {content: \"\\f014\";}\n\ -.fa-home:before {content: \"\\f015\";}\n\ -.fa-file-o:before {content: \"\\f016\";}\n\ -.fa-clock-o:before {content: \"\\f017\";}\n\ -.fa-road:before {content: \"\\f018\";}\n\ -.fa-download:before {content: \"\\f019\";}\n\ -.fa-arrow-circle-o-down:before {content: \"\\f01a\";}\n\ -.fa-arrow-circle-o-up:before {content: \"\\f01b\";}\n\ -.fa-inbox:before {content: \"\\f01c\";}\n\ -.fa-play-circle-o:before {content: \"\\f01d\";}\n\ -.fa-rotate-right:before, .fa-repeat:before {content: \"\\f01e\";}\n\ -.fa-refresh:before {content: \"\\f021\";}\n\ -.fa-list-alt:before {content: \"\\f022\";}\n\ -.fa-lock:before {content: \"\\f023\";}\n\ -.fa-flag:before {content: \"\\f024\";}\n\ -.fa-headphones:before {content: \"\\f025\";}\n\ -.fa-volume-off:before {content: \"\\f026\";}\n\ -.fa-volume-down:before {content: \"\\f027\";}\n\ -.fa-volume-up:before {content: \"\\f028\";}\n\ -.fa-qrcode:before {content: \"\\f029\";}\n\ -.fa-barcode:before {content: \"\\f02a\";}\n\ -.fa-tag:before {content: \"\\f02b\";}\n\ -.fa-tags:before {content: \"\\f02c\";}\n\ -.fa-book:before {content: \"\\f02d\";}\n\ -.fa-bookmark:before {content: \"\\f02e\";}\n\ -.fa-print:before {content: \"\\f02f\";}\n\ -.fa-camera:before {content: \"\\f030\";}\n\ -.fa-font:before {content: \"\\f031\";}\n\ -.fa-bold:before {content: \"\\f032\";}\n\ -.fa-italic:before {content: \"\\f033\";}\n\ -.fa-text-height:before {content: \"\\f034\";}\n\ -.fa-text-width:before {content: \"\\f035\";}\n\ -.fa-align-left:before {content: \"\\f036\";}\n\ -.fa-align-center:before {content: \"\\f037\";}\n\ -.fa-align-right:before {content: \"\\f038\";}\n\ -.fa-align-justify:before {content: \"\\f039\";}\n\ -.fa-list:before {content: \"\\f03a\";}\n\ -.fa-dedent:before, .fa-outdent:before {content: \"\\f03b\";}\n\ -.fa-indent:before {content: \"\\f03c\";}\n\ -.fa-video-camera:before {content: \"\\f03d\";}\n\ -.fa-photo:before, .fa-image:before, .fa-picture-o:before {content: \"\\f03e\";}\n\ -.fa-pencil:before {content: \"\\f040\";}\n\ -.fa-map-marker:before {content: \"\\f041\";}\n\ -.fa-adjust:before {content: \"\\f042\";}\n\ -.fa-tint:before {content: \"\\f043\";}\n\ -.fa-edit:before, .fa-pencil-square-o:before {content: \"\\f044\";}\n\ -.fa-share-square-o:before {content: \"\\f045\";}\n\ -.fa-check-square-o:before {content: \"\\f046\";}\n\ -.fa-arrows:before {content: \"\\f047\";}\n\ -.fa-step-backward:before {content: \"\\f048\";}\n\ -.fa-fast-backward:before {content: \"\\f049\";}\n\ -.fa-backward:before {content: \"\\f04a\";}\n\ -.fa-play:before {content: \"\\f04b\";}\n\ -.fa-pause:before {content: \"\\f04c\";}\n\ -.fa-stop:before {content: \"\\f04d\";}\n\ -.fa-forward:before {content: \"\\f04e\";}\n\ -.fa-fast-forward:before {content: \"\\f050\";}\n\ -.fa-step-forward:before {content: \"\\f051\";}\n\ -.fa-eject:before {content: \"\\f052\";}\n\ -.fa-chevron-left:before {content: \"\\f053\";}\n\ -.fa-chevron-right:before {content: \"\\f054\";}\n\ -.fa-plus-circle:before {content: \"\\f055\";}\n\ -.fa-minus-circle:before {content: \"\\f056\";}\n\ -.fa-times-circle:before {content: \"\\f057\";}\n\ -.fa-check-circle:before {content: \"\\f058\";}\n\ -.fa-question-circle:before {content: \"\\f059\";}\n\ -.fa-info-circle:before {content: \"\\f05a\";}\n\ -.fa-crosshairs:before {content: \"\\f05b\";}\n\ -.fa-times-circle-o:before {content: \"\\f05c\";}\n\ -.fa-check-circle-o:before {content: \"\\f05d\";}\n\ -.fa-ban:before {content: \"\\f05e\";}\n\ -.fa-arrow-left:before {content: \"\\f060\";}\n\ -.fa-arrow-right:before {content: \"\\f061\";}\n\ -.fa-arrow-up:before {content: \"\\f062\";}\n\ -.fa-arrow-down:before {content: \"\\f063\";}\n\ -.fa-mail-forward:before, .fa-share:before {content: \"\\f064\";}\n\ -.fa-expand:before {content: \"\\f065\";}\n\ -.fa-compress:before {content: \"\\f066\";}\n\ -.fa-plus:before {content: \"\\f067\";}\n\ -.fa-minus:before {content: \"\\f068\";}\n\ -.fa-asterisk:before {content: \"\\f069\";}\n\ -.fa-exclamation-circle:before {content: \"\\f06a\";}\n\ -.fa-gift:before {content: \"\\f06b\";}\n\ -.fa-leaf:before {content: \"\\f06c\";}\n\ -.fa-fire:before {content: \"\\f06d\";}\n\ -.fa-eye:before {content: \"\\f06e\";}\n\ -.fa-eye-slash:before {content: \"\\f070\";}\n\ -.fa-warning:before, .fa-exclamation-triangle:before {content: \"\\f071\";}\n\ -.fa-plane:before {content: \"\\f072\";}\n\ -.fa-calendar:before {content: \"\\f073\";}\n\ -.fa-random:before {content: \"\\f074\";}\n\ -.fa-comment:before {content: \"\\f075\";}\n\ -.fa-magnet:before {content: \"\\f076\";}\n\ -.fa-chevron-up:before {content: \"\\f077\";}\n\ -.fa-chevron-down:before {content: \"\\f078\";}\n\ -.fa-retweet:before {content: \"\\f079\";}\n\ -.fa-shopping-cart:before {content: \"\\f07a\";}\n\ -.fa-folder:before {content: \"\\f07b\";}\n\ -.fa-folder-open:before {content: \"\\f07c\";}\n\ -.fa-arrows-v:before {content: \"\\f07d\";}\n\ -.fa-arrows-h:before {content: \"\\f07e\";}\n\ -.fa-bar-chart-o:before, .fa-bar-chart:before {content: \"\\f080\";}\n\ -.fa-twitter-square:before {content: \"\\f081\";}\n\ -.fa-facebook-square:before {content: \"\\f082\";}\n\ -.fa-camera-retro:before {content: \"\\f083\";}\n\ -.fa-key:before {content: \"\\f084\";}\n\ -.fa-gears:before, .fa-cogs:before {content: \"\\f085\";}\n\ -.fa-comments:before {content: \"\\f086\";}\n\ -.fa-thumbs-o-up:before {content: \"\\f087\";}\n\ -.fa-thumbs-o-down:before {content: \"\\f088\";}\n\ -.fa-star-half:before {content: \"\\f089\";}\n\ -.fa-heart-o:before {content: \"\\f08a\";}\n\ -.fa-sign-out:before {content: \"\\f08b\";}\n\ -.fa-linkedin-square:before {content: \"\\f08c\";}\n\ -.fa-thumb-tack:before {content: \"\\f08d\";}\n\ -.fa-external-link:before {content: \"\\f08e\";}\n\ -.fa-sign-in:before {content: \"\\f090\";}\n\ -.fa-trophy:before {content: \"\\f091\";}\n\ -.fa-github-square:before {content: \"\\f092\";}\n\ -.fa-upload:before {content: \"\\f093\";}\n\ -.fa-lemon-o:before {content: \"\\f094\";}\n\ -.fa-phone:before {content: \"\\f095\";}\n\ -.fa-square-o:before {content: \"\\f096\";}\n\ -.fa-bookmark-o:before {content: \"\\f097\";}\n\ -.fa-phone-square:before {content: \"\\f098\";}\n\ -.fa-twitter:before {content: \"\\f099\";}\n\ -.fa-facebook-f:before, .fa-facebook:before {content: \"\\f09a\";}\n\ -.fa-github:before {content: \"\\f09b\";}\n\ -.fa-unlock:before {content: \"\\f09c\";}\n\ -.fa-credit-card:before {content: \"\\f09d\";}\n\ -.fa-feed:before, .fa-rss:before {content: \"\\f09e\";}\n\ -.fa-hdd-o:before {content: \"\\f0a0\";}\n\ -.fa-bullhorn:before {content: \"\\f0a1\";}\n\ -.fa-bell:before {content: \"\\f0f3\";}\n\ -.fa-certificate:before {content: \"\\f0a3\";}\n\ -.fa-hand-o-right:before {content: \"\\f0a4\";}\n\ -.fa-hand-o-left:before {content: \"\\f0a5\";}\n\ -.fa-hand-o-up:before {content: \"\\f0a6\";}\n\ -.fa-hand-o-down:before {content: \"\\f0a7\";}\n\ -.fa-arrow-circle-left:before {content: \"\\f0a8\";}\n\ -.fa-arrow-circle-right:before {content: \"\\f0a9\";}\n\ -.fa-arrow-circle-up:before {content: \"\\f0aa\";}\n\ -.fa-arrow-circle-down:before {content: \"\\f0ab\";}\n\ -.fa-globe:before {content: \"\\f0ac\";}\n\ -.fa-wrench:before {content: \"\\f0ad\";}\n\ -.fa-tasks:before {content: \"\\f0ae\";}\n\ -.fa-filter:before {content: \"\\f0b0\";}\n\ -.fa-briefcase:before {content: \"\\f0b1\";}\n\ -.fa-arrows-alt:before {content: \"\\f0b2\";}\n\ -.fa-group:before, .fa-users:before {content: \"\\f0c0\";}\n\ -.fa-chain:before, .fa-link:before {content: \"\\f0c1\";}\n\ -.fa-cloud:before {content: \"\\f0c2\";}\n\ -.fa-flask:before {content: \"\\f0c3\";}\n\ -.fa-cut:before, .fa-scissors:before {content: \"\\f0c4\";}\n\ -.fa-copy:before, .fa-files-o:before {content: \"\\f0c5\";}\n\ -.fa-paperclip:before {content: \"\\f0c6\";}\n\ -.fa-save:before, .fa-floppy-o:before {content: \"\\f0c7\";}\n\ -.fa-square:before {content: \"\\f0c8\";}\n\ -.fa-navicon:before, .fa-reorder:before, .fa-bars:before {content: \"\\f0c9\";}\n\ -.fa-list-ul:before {content: \"\\f0ca\";}\n\ -.fa-list-ol:before {content: \"\\f0cb\";}\n\ -.fa-strikethrough:before {content: \"\\f0cc\";}\n\ -.fa-underline:before {content: \"\\f0cd\";}\n\ -.fa-table:before {content: \"\\f0ce\";}\n\ -.fa-magic:before {content: \"\\f0d0\";}\n\ -.fa-truck:before {content: \"\\f0d1\";}\n\ -.fa-pinterest:before {content: \"\\f0d2\";}\n\ -.fa-pinterest-square:before {content: \"\\f0d3\";}\n\ -.fa-google-plus-square:before {content: \"\\f0d4\";}\n\ -.fa-google-plus:before {content: \"\\f0d5\";}\n\ -.fa-money:before {content: \"\\f0d6\";}\n\ -.fa-caret-down:before {content: \"\\f0d7\";}\n\ -.fa-caret-up:before {content: \"\\f0d8\";}\n\ -.fa-caret-left:before {content: \"\\f0d9\";}\n\ -.fa-caret-right:before {content: \"\\f0da\";}\n\ -.fa-columns:before {content: \"\\f0db\";}\n\ -.fa-unsorted:before, .fa-sort:before {content: \"\\f0dc\";}\n\ -.fa-sort-down:before, .fa-sort-desc:before {content: \"\\f0dd\";}\n\ -.fa-sort-up:before, .fa-sort-asc:before {content: \"\\f0de\";}\n\ -.fa-envelope:before {content: \"\\f0e0\";}\n\ -.fa-linkedin:before {content: \"\\f0e1\";}\n\ -.fa-rotate-left:before, .fa-undo:before {content: \"\\f0e2\";}\n\ -.fa-legal:before, .fa-gavel:before {content: \"\\f0e3\";}\n\ -.fa-dashboard:before, .fa-tachometer:before {content: \"\\f0e4\";}\n\ -.fa-comment-o:before {content: \"\\f0e5\";}\n\ -.fa-comments-o:before {content: \"\\f0e6\";}\n\ -.fa-flash:before, .fa-bolt:before {content: \"\\f0e7\";}\n\ -.fa-sitemap:before {content: \"\\f0e8\";}\n\ -.fa-umbrella:before {content: \"\\f0e9\";}\n\ -.fa-paste:before, .fa-clipboard:before {content: \"\\f0ea\";}\n\ -.fa-lightbulb-o:before {content: \"\\f0eb\";}\n\ -.fa-exchange:before {content: \"\\f0ec\";}\n\ -.fa-cloud-download:before {content: \"\\f0ed\";}\n\ -.fa-cloud-upload:before {content: \"\\f0ee\";}\n\ -.fa-user-md:before {content: \"\\f0f0\";}\n\ -.fa-stethoscope:before {content: \"\\f0f1\";}\n\ -.fa-suitcase:before {content: \"\\f0f2\";}\n\ -.fa-bell-o:before {content: \"\\f0a2\";}\n\ -.fa-coffee:before {content: \"\\f0f4\";}\n\ -.fa-cutlery:before {content: \"\\f0f5\";}\n\ -.fa-file-text-o:before {content: \"\\f0f6\";}\n\ -.fa-building-o:before {content: \"\\f0f7\";}\n\ -.fa-hospital-o:before {content: \"\\f0f8\";}\n\ -.fa-ambulance:before {content: \"\\f0f9\";}\n\ -.fa-medkit:before {content: \"\\f0fa\";}\n\ -.fa-fighter-jet:before {content: \"\\f0fb\";}\n\ -.fa-beer:before {content: \"\\f0fc\";}\n\ -.fa-h-square:before {content: \"\\f0fd\";}\n\ -.fa-plus-square:before {content: \"\\f0fe\";}\n\ -.fa-angle-double-left:before {content: \"\\f100\";}\n\ -.fa-angle-double-right:before {content: \"\\f101\";}\n\ -.fa-angle-double-up:before {content: \"\\f102\";}\n\ -.fa-angle-double-down:before {content: \"\\f103\";}\n\ -.fa-angle-left:before {content: \"\\f104\";}\n\ -.fa-angle-right:before {content: \"\\f105\";}\n\ -.fa-angle-up:before {content: \"\\f106\";}\n\ -.fa-angle-down:before {content: \"\\f107\";}\n\ -.fa-desktop:before {content: \"\\f108\";}\n\ -.fa-laptop:before {content: \"\\f109\";}\n\ -.fa-tablet:before {content: \"\\f10a\";}\n\ -.fa-mobile-phone:before, .fa-mobile:before {content: \"\\f10b\";}\n\ -.fa-circle-o:before {content: \"\\f10c\";}\n\ -.fa-quote-left:before {content: \"\\f10d\";}\n\ -.fa-quote-right:before {content: \"\\f10e\";}\n\ -.fa-spinner:before {content: \"\\f110\";}\n\ -.fa-circle:before {content: \"\\f111\";}\n\ -.fa-mail-reply:before, .fa-reply:before {content: \"\\f112\";}\n\ -.fa-github-alt:before {content: \"\\f113\";}\n\ -.fa-folder-o:before {content: \"\\f114\";}\n\ -.fa-folder-open-o:before {content: \"\\f115\";}\n\ -.fa-smile-o:before {content: \"\\f118\";}\n\ -.fa-frown-o:before {content: \"\\f119\";}\n\ -.fa-meh-o:before {content: \"\\f11a\";}\n\ -.fa-gamepad:before {content: \"\\f11b\";}\n\ -.fa-keyboard-o:before {content: \"\\f11c\";}\n\ -.fa-flag-o:before {content: \"\\f11d\";}\n\ -.fa-flag-checkered:before {content: \"\\f11e\";}\n\ -.fa-terminal:before {content: \"\\f120\";}\n\ -.fa-code:before {content: \"\\f121\";}\n\ -.fa-mail-reply-all:before, .fa-reply-all:before {content: \"\\f122\";}\n\ -.fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before {content: \"\\f123\";}\n\ -.fa-location-arrow:before {content: \"\\f124\";}\n\ -.fa-crop:before {content: \"\\f125\";}\n\ -.fa-code-fork:before {content: \"\\f126\";}\n\ -.fa-unlink:before, .fa-chain-broken:before {content: \"\\f127\";}\n\ -.fa-question:before {content: \"\\f128\";}\n\ -.fa-info:before {content: \"\\f129\";}\n\ -.fa-exclamation:before {content: \"\\f12a\";}\n\ -.fa-superscript:before {content: \"\\f12b\";}\n\ -.fa-subscript:before {content: \"\\f12c\";}\n\ -.fa-eraser:before {content: \"\\f12d\";}\n\ -.fa-puzzle-piece:before {content: \"\\f12e\";}\n\ -.fa-microphone:before {content: \"\\f130\";}\n\ -.fa-microphone-slash:before {content: \"\\f131\";}\n\ -.fa-shield:before {content: \"\\f132\";}\n\ -.fa-calendar-o:before {content: \"\\f133\";}\n\ -.fa-fire-extinguisher:before {content: \"\\f134\";}\n\ -.fa-rocket:before {content: \"\\f135\";}\n\ -.fa-maxcdn:before {content: \"\\f136\";}\n\ -.fa-chevron-circle-left:before {content: \"\\f137\";}\n\ -.fa-chevron-circle-right:before {content: \"\\f138\";}\n\ -.fa-chevron-circle-up:before {content: \"\\f139\";}\n\ -.fa-chevron-circle-down:before {content: \"\\f13a\";}\n\ -.fa-html5:before {content: \"\\f13b\";}\n\ -.fa-css3:before {content: \"\\f13c\";}\n\ -.fa-anchor:before {content: \"\\f13d\";}\n\ -.fa-unlock-alt:before {content: \"\\f13e\";}\n\ -.fa-bullseye:before {content: \"\\f140\";}\n\ -.fa-ellipsis-h:before {content: \"\\f141\";}\n\ -.fa-ellipsis-v:before {content: \"\\f142\";}\n\ -.fa-rss-square:before {content: \"\\f143\";}\n\ -.fa-play-circle:before {content: \"\\f144\";}\n\ -.fa-ticket:before {content: \"\\f145\";}\n\ -.fa-minus-square:before {content: \"\\f146\";}\n\ -.fa-minus-square-o:before {content: \"\\f147\";}\n\ -.fa-level-up:before {content: \"\\f148\";}\n\ -.fa-level-down:before {content: \"\\f149\";}\n\ -.fa-check-square:before {content: \"\\f14a\";}\n\ -.fa-pencil-square:before {content: \"\\f14b\";}\n\ -.fa-external-link-square:before {content: \"\\f14c\";}\n\ -.fa-share-square:before {content: \"\\f14d\";}\n\ -.fa-compass:before {content: \"\\f14e\";}\n\ -.fa-toggle-down:before, .fa-caret-square-o-down:before {content: \"\\f150\";}\n\ -.fa-toggle-up:before, .fa-caret-square-o-up:before {content: \"\\f151\";}\n\ -.fa-toggle-right:before, .fa-caret-square-o-right:before {content: \"\\f152\";}\n\ -.fa-euro:before, .fa-eur:before {content: \"\\f153\";}\n\ -.fa-gbp:before {content: \"\\f154\";}\n\ -.fa-dollar:before, .fa-usd:before {content: \"\\f155\";}\n\ -.fa-rupee:before, .fa-inr:before {content: \"\\f156\";}\n\ -.fa-cny:before, .fa-rmb:before, .fa-yen:before, .fa-jpy:before {content: \"\\f157\";}\n\ -.fa-ruble:before, .fa-rouble:before, .fa-rub:before {content: \"\\f158\";}\n\ -.fa-won:before, .fa-krw:before {content: \"\\f159\";}\n\ -.fa-bitcoin:before, .fa-btc:before {content: \"\\f15a\";}\n\ -.fa-file:before {content: \"\\f15b\";}\n\ -.fa-file-text:before {content: \"\\f15c\";}\n\ -.fa-sort-alpha-asc:before {content: \"\\f15d\";}\n\ -.fa-sort-alpha-desc:before {content: \"\\f15e\";}\n\ -.fa-sort-amount-asc:before {content: \"\\f160\";}\n\ -.fa-sort-amount-desc:before {content: \"\\f161\";}\n\ -.fa-sort-numeric-asc:before {content: \"\\f162\";}\n\ -.fa-sort-numeric-desc:before {content: \"\\f163\";}\n\ -.fa-thumbs-up:before {content: \"\\f164\";}\n\ -.fa-thumbs-down:before {content: \"\\f165\";}\n\ -.fa-youtube-square:before {content: \"\\f166\";}\n\ -.fa-youtube:before {content: \"\\f167\";}\n\ -.fa-xing:before {content: \"\\f168\";}\n\ -.fa-xing-square:before {content: \"\\f169\";}\n\ -.fa-youtube-play:before {content: \"\\f16a\";}\n\ -.fa-dropbox:before {content: \"\\f16b\";}\n\ -.fa-stack-overflow:before {content: \"\\f16c\";}\n\ -.fa-instagram:before {content: \"\\f16d\";}\n\ -.fa-flickr:before {content: \"\\f16e\";}\n\ -.fa-adn:before {content: \"\\f170\";}\n\ -.fa-bitbucket:before {content: \"\\f171\";}\n\ -.fa-bitbucket-square:before {content: \"\\f172\";}\n\ -.fa-tumblr:before {content: \"\\f173\";}\n\ -.fa-tumblr-square:before {content: \"\\f174\";}\n\ -.fa-long-arrow-down:before {content: \"\\f175\";}\n\ -.fa-long-arrow-up:before {content: \"\\f176\";}\n\ -.fa-long-arrow-left:before {content: \"\\f177\";}\n\ -.fa-long-arrow-right:before {content: \"\\f178\";}\n\ -.fa-apple:before {content: \"\\f179\";}\n\ -.fa-windows:before {content: \"\\f17a\";}\n\ -.fa-android:before {content: \"\\f17b\";}\n\ -.fa-linux:before {content: \"\\f17c\";}\n\ -.fa-dribbble:before {content: \"\\f17d\";}\n\ -.fa-skype:before {content: \"\\f17e\";}\n\ -.fa-foursquare:before {content: \"\\f180\";}\n\ -.fa-trello:before {content: \"\\f181\";}\n\ -.fa-female:before {content: \"\\f182\";}\n\ -.fa-male:before {content: \"\\f183\";}\n\ -.fa-gittip:before, .fa-gratipay:before {content: \"\\f184\";}\n\ -.fa-sun-o:before {content: \"\\f185\";}\n\ -.fa-moon-o:before {content: \"\\f186\";}\n\ -.fa-archive:before {content: \"\\f187\";}\n\ -.fa-bug:before {content: \"\\f188\";}\n\ -.fa-vk:before {content: \"\\f189\";}\n\ -.fa-weibo:before {content: \"\\f18a\";}\n\ -.fa-renren:before {content: \"\\f18b\";}\n\ -.fa-pagelines:before {content: \"\\f18c\";}\n\ -.fa-stack-exchange:before {content: \"\\f18d\";}\n\ -.fa-arrow-circle-o-right:before {content: \"\\f18e\";}\n\ -.fa-arrow-circle-o-left:before {content: \"\\f190\";}\n\ -.fa-toggle-left:before, .fa-caret-square-o-left:before {content: \"\\f191\";}\n\ -.fa-dot-circle-o:before {content: \"\\f192\";}\n\ -.fa-wheelchair:before {content: \"\\f193\";}\n\ -.fa-vimeo-square:before {content: \"\\f194\";}\n\ -.fa-turkish-lira:before, .fa-try:before {content: \"\\f195\";}\n\ -.fa-plus-square-o:before {content: \"\\f196\";}\n\ -.fa-space-shuttle:before {content: \"\\f197\";}\n\ -.fa-slack:before {content: \"\\f198\";}\n\ -.fa-envelope-square:before {content: \"\\f199\";}\n\ -.fa-wordpress:before {content: \"\\f19a\";}\n\ -.fa-openid:before {content: \"\\f19b\";}\n\ -.fa-institution:before, .fa-bank:before, .fa-university:before {content: \"\\f19c\";}\n\ -.fa-mortar-board:before, .fa-graduation-cap:before {content: \"\\f19d\";}\n\ -.fa-yahoo:before {content: \"\\f19e\";}\n\ -.fa-google:before {content: \"\\f1a0\";}\n\ -.fa-reddit:before {content: \"\\f1a1\";}\n\ -.fa-reddit-square:before {content: \"\\f1a2\";}\n\ -.fa-stumbleupon-circle:before {content: \"\\f1a3\";}\n\ -.fa-stumbleupon:before {content: \"\\f1a4\";}\n\ -.fa-delicious:before {content: \"\\f1a5\";}\n\ -.fa-digg:before {content: \"\\f1a6\";}\n\ -.fa-pied-piper-pp:before {content: \"\\f1a7\";}\n\ -.fa-pied-piper-alt:before {content: \"\\f1a8\";}\n\ -.fa-drupal:before {content: \"\\f1a9\";}\n\ -.fa-joomla:before {content: \"\\f1aa\";}\n\ -.fa-language:before {content: \"\\f1ab\";}\n\ -.fa-fax:before {content: \"\\f1ac\";}\n\ -.fa-building:before {content: \"\\f1ad\";}\n\ -.fa-child:before {content: \"\\f1ae\";}\n\ -.fa-paw:before {content: \"\\f1b0\";}\n\ -.fa-spoon:before {content: \"\\f1b1\";}\n\ -.fa-cube:before {content: \"\\f1b2\";}\n\ -.fa-cubes:before {content: \"\\f1b3\";}\n\ -.fa-behance:before {content: \"\\f1b4\";}\n\ -.fa-behance-square:before {content: \"\\f1b5\";}\n\ -.fa-steam:before {content: \"\\f1b6\";}\n\ -.fa-steam-square:before {content: \"\\f1b7\";}\n\ -.fa-recycle:before {content: \"\\f1b8\";}\n\ -.fa-automobile:before, .fa-car:before {content: \"\\f1b9\";}\n\ -.fa-cab:before, .fa-taxi:before {content: \"\\f1ba\";}\n\ -.fa-tree:before {content: \"\\f1bb\";}\n\ -.fa-spotify:before {content: \"\\f1bc\";}\n\ -.fa-deviantart:before {content: \"\\f1bd\";}\n\ -.fa-soundcloud:before {content: \"\\f1be\";}\n\ -.fa-database:before {content: \"\\f1c0\";}\n\ -.fa-file-pdf-o:before {content: \"\\f1c1\";}\n\ -.fa-file-word-o:before {content: \"\\f1c2\";}\n\ -.fa-file-excel-o:before {content: \"\\f1c3\";}\n\ -.fa-file-powerpoint-o:before {content: \"\\f1c4\";}\n\ -.fa-file-photo-o:before, .fa-file-picture-o:before, .fa-file-image-o:before {content: \"\\f1c5\";}\n\ -.fa-file-zip-o:before, .fa-file-archive-o:before {content: \"\\f1c6\";}\n\ -.fa-file-sound-o:before, .fa-file-audio-o:before {content: \"\\f1c7\";}\n\ -.fa-file-movie-o:before, .fa-file-video-o:before {content: \"\\f1c8\";}\n\ -.fa-file-code-o:before {content: \"\\f1c9\";}\n\ -.fa-vine:before {content: \"\\f1ca\";}\n\ -.fa-codepen:before {content: \"\\f1cb\";}\n\ -.fa-jsfiddle:before {content: \"\\f1cc\";}\n\ -.fa-life-bouy:before, .fa-life-buoy:before, .fa-life-saver:before, .fa-support:before, .fa-life-ring:before {content: \"\\f1cd\";}\n\ -.fa-circle-o-notch:before {content: \"\\f1ce\";}\n\ -.fa-ra:before, .fa-resistance:before, .fa-rebel:before {content: \"\\f1d0\";}\n\ -.fa-ge:before, .fa-empire:before {content: \"\\f1d1\";}\n\ -.fa-git-square:before {content: \"\\f1d2\";}\n\ -.fa-git:before {content: \"\\f1d3\";}\n\ -.fa-y-combinator-square:before, .fa-yc-square:before, .fa-hacker-news:before {content: \"\\f1d4\";}\n\ -.fa-tencent-weibo:before {content: \"\\f1d5\";}\n\ -.fa-qq:before {content: \"\\f1d6\";}\n\ -.fa-wechat:before, .fa-weixin:before {content: \"\\f1d7\";}\n\ -.fa-send:before, .fa-paper-plane:before {content: \"\\f1d8\";}\n\ -.fa-send-o:before, .fa-paper-plane-o:before {content: \"\\f1d9\";}\n\ -.fa-history:before {content: \"\\f1da\";}\n\ -.fa-circle-thin:before {content: \"\\f1db\";}\n\ -.fa-header:before {content: \"\\f1dc\";}\n\ -.fa-paragraph:before {content: \"\\f1dd\";}\n\ -.fa-sliders:before {content: \"\\f1de\";}\n\ -.fa-share-alt:before {content: \"\\f1e0\";}\n\ -.fa-share-alt-square:before {content: \"\\f1e1\";}\n\ -.fa-bomb:before {content: \"\\f1e2\";}\n\ -.fa-soccer-ball-o:before, .fa-futbol-o:before {content: \"\\f1e3\";}\n\ -.fa-tty:before {content: \"\\f1e4\";}\n\ -.fa-binoculars:before {content: \"\\f1e5\";}\n\ -.fa-plug:before {content: \"\\f1e6\";}\n\ -.fa-slideshare:before {content: \"\\f1e7\";}\n\ -.fa-twitch:before {content: \"\\f1e8\";}\n\ -.fa-yelp:before {content: \"\\f1e9\";}\n\ -.fa-newspaper-o:before {content: \"\\f1ea\";}\n\ -.fa-wifi:before {content: \"\\f1eb\";}\n\ -.fa-calculator:before {content: \"\\f1ec\";}\n\ -.fa-paypal:before {content: \"\\f1ed\";}\n\ -.fa-google-wallet:before {content: \"\\f1ee\";}\n\ -.fa-cc-visa:before {content: \"\\f1f0\";}\n\ -.fa-cc-mastercard:before {content: \"\\f1f1\";}\n\ -.fa-cc-discover:before {content: \"\\f1f2\";}\n\ -.fa-cc-amex:before {content: \"\\f1f3\";}\n\ -.fa-cc-paypal:before {content: \"\\f1f4\";}\n\ -.fa-cc-stripe:before {content: \"\\f1f5\";}\n\ -.fa-bell-slash:before {content: \"\\f1f6\";}\n\ -.fa-bell-slash-o:before {content: \"\\f1f7\";}\n\ -.fa-trash:before {content: \"\\f1f8\";}\n\ -.fa-copyright:before {content: \"\\f1f9\";}\n\ -.fa-at:before {content: \"\\f1fa\";}\n\ -.fa-eyedropper:before {content: \"\\f1fb\";}\n\ -.fa-paint-brush:before {content: \"\\f1fc\";}\n\ -.fa-birthday-cake:before {content: \"\\f1fd\";}\n\ -.fa-area-chart:before {content: \"\\f1fe\";}\n\ -.fa-pie-chart:before {content: \"\\f200\";}\n\ -.fa-line-chart:before {content: \"\\f201\";}\n\ -.fa-lastfm:before {content: \"\\f202\";}\n\ -.fa-lastfm-square:before {content: \"\\f203\";}\n\ -.fa-toggle-off:before {content: \"\\f204\";}\n\ -.fa-toggle-on:before {content: \"\\f205\";}\n\ -.fa-bicycle:before {content: \"\\f206\";}\n\ -.fa-bus:before {content: \"\\f207\";}\n\ -.fa-ioxhost:before {content: \"\\f208\";}\n\ -.fa-angellist:before {content: \"\\f209\";}\n\ -.fa-cc:before {content: \"\\f20a\";}\n\ -.fa-shekel:before, .fa-sheqel:before, .fa-ils:before {content: \"\\f20b\";}\n\ -.fa-meanpath:before {content: \"\\f20c\";}\n\ -.fa-buysellads:before {content: \"\\f20d\";}\n\ -.fa-connectdevelop:before {content: \"\\f20e\";}\n\ -.fa-dashcube:before {content: \"\\f210\";}\n\ -.fa-forumbee:before {content: \"\\f211\";}\n\ -.fa-leanpub:before {content: \"\\f212\";}\n\ -.fa-sellsy:before {content: \"\\f213\";}\n\ -.fa-shirtsinbulk:before {content: \"\\f214\";}\n\ -.fa-simplybuilt:before {content: \"\\f215\";}\n\ -.fa-skyatlas:before {content: \"\\f216\";}\n\ -.fa-cart-plus:before {content: \"\\f217\";}\n\ -.fa-cart-arrow-down:before {content: \"\\f218\";}\n\ -.fa-diamond:before {content: \"\\f219\";}\n\ -.fa-ship:before {content: \"\\f21a\";}\n\ -.fa-user-secret:before {content: \"\\f21b\";}\n\ -.fa-motorcycle:before {content: \"\\f21c\";}\n\ -.fa-street-view:before {content: \"\\f21d\";}\n\ -.fa-heartbeat:before {content: \"\\f21e\";}\n\ -.fa-venus:before {content: \"\\f221\";}\n\ -.fa-mars:before {content: \"\\f222\";}\n\ -.fa-mercury:before {content: \"\\f223\";}\n\ -.fa-intersex:before, .fa-transgender:before {content: \"\\f224\";}\n\ -.fa-transgender-alt:before {content: \"\\f225\";}\n\ -.fa-venus-double:before {content: \"\\f226\";}\n\ -.fa-mars-double:before {content: \"\\f227\";}\n\ -.fa-venus-mars:before {content: \"\\f228\";}\n\ -.fa-mars-stroke:before {content: \"\\f229\";}\n\ -.fa-mars-stroke-v:before {content: \"\\f22a\";}\n\ -.fa-mars-stroke-h:before {content: \"\\f22b\";}\n\ -.fa-neuter:before {content: \"\\f22c\";}\n\ -.fa-genderless:before {content: \"\\f22d\";}\n\ -.fa-facebook-official:before {content: \"\\f230\";}\n\ -.fa-pinterest-p:before {content: \"\\f231\";}\n\ -.fa-whatsapp:before {content: \"\\f232\";}\n\ -.fa-server:before {content: \"\\f233\";}\n\ -.fa-user-plus:before {content: \"\\f234\";}\n\ -.fa-user-times:before {content: \"\\f235\";}\n\ -.fa-hotel:before, .fa-bed:before {content: \"\\f236\";}\n\ -.fa-viacoin:before {content: \"\\f237\";}\n\ -.fa-train:before {content: \"\\f238\";}\n\ -.fa-subway:before {content: \"\\f239\";}\n\ -.fa-medium:before {content: \"\\f23a\";}\n\ -.fa-yc:before, .fa-y-combinator:before {content: \"\\f23b\";}\n\ -.fa-optin-monster:before {content: \"\\f23c\";}\n\ -.fa-opencart:before {content: \"\\f23d\";}\n\ -.fa-expeditedssl:before {content: \"\\f23e\";}\n\ -.fa-battery-4:before, .fa-battery:before, .fa-battery-full:before {content: \"\\f240\";}\n\ -.fa-battery-3:before, .fa-battery-three-quarters:before {content: \"\\f241\";}\n\ -.fa-battery-2:before, .fa-battery-half:before {content: \"\\f242\";}\n\ -.fa-battery-1:before, .fa-battery-quarter:before {content: \"\\f243\";}\n\ -.fa-battery-0:before, .fa-battery-empty:before {content: \"\\f244\";}\n\ -.fa-mouse-pointer:before {content: \"\\f245\";}\n\ -.fa-i-cursor:before {content: \"\\f246\";}\n\ -.fa-object-group:before {content: \"\\f247\";}\n\ -.fa-object-ungroup:before {content: \"\\f248\";}\n\ -.fa-sticky-note:before {content: \"\\f249\";}\n\ -.fa-sticky-note-o:before {content: \"\\f24a\";}\n\ -.fa-cc-jcb:before {content: \"\\f24b\";}\n\ -.fa-cc-diners-club:before {content: \"\\f24c\";}\n\ -.fa-clone:before {content: \"\\f24d\";}\n\ -.fa-balance-scale:before {content: \"\\f24e\";}\n\ -.fa-hourglass-o:before {content: \"\\f250\";}\n\ -.fa-hourglass-1:before, .fa-hourglass-start:before {content: \"\\f251\";}\n\ -.fa-hourglass-2:before, .fa-hourglass-half:before {content: \"\\f252\";}\n\ -.fa-hourglass-3:before, .fa-hourglass-end:before {content: \"\\f253\";}\n\ -.fa-hourglass:before {content: \"\\f254\";}\n\ -.fa-hand-grab-o:before, .fa-hand-rock-o:before {content: \"\\f255\";}\n\ -.fa-hand-stop-o:before, .fa-hand-paper-o:before {content: \"\\f256\";}\n\ -.fa-hand-scissors-o:before {content: \"\\f257\";}\n\ -.fa-hand-lizard-o:before {content: \"\\f258\";}\n\ -.fa-hand-spock-o:before {content: \"\\f259\";}\n\ -.fa-hand-pointer-o:before {content: \"\\f25a\";}\n\ -.fa-hand-peace-o:before {content: \"\\f25b\";}\n\ -.fa-trademark:before {content: \"\\f25c\";}\n\ -.fa-registered:before {content: \"\\f25d\";}\n\ -.fa-creative-commons:before {content: \"\\f25e\";}\n\ -.fa-gg:before {content: \"\\f260\";}\n\ -.fa-gg-circle:before {content: \"\\f261\";}\n\ -.fa-tripadvisor:before {content: \"\\f262\";}\n\ -.fa-odnoklassniki:before {content: \"\\f263\";}\n\ -.fa-odnoklassniki-square:before {content: \"\\f264\";}\n\ -.fa-get-pocket:before {content: \"\\f265\";}\n\ -.fa-wikipedia-w:before {content: \"\\f266\";}\n\ -.fa-safari:before {content: \"\\f267\";}\n\ -.fa-chrome:before {content: \"\\f268\";}\n\ -.fa-firefox:before {content: \"\\f269\";}\n\ -.fa-opera:before {content: \"\\f26a\";}\n\ -.fa-internet-explorer:before {content: \"\\f26b\";}\n\ -.fa-tv:before, .fa-television:before {content: \"\\f26c\";}\n\ -.fa-contao:before {content: \"\\f26d\";}\n\ -.fa-500px:before {content: \"\\f26e\";}\n\ -.fa-amazon:before {content: \"\\f270\";}\n\ -.fa-calendar-plus-o:before {content: \"\\f271\";}\n\ -.fa-calendar-minus-o:before {content: \"\\f272\";}\n\ -.fa-calendar-times-o:before {content: \"\\f273\";}\n\ -.fa-calendar-check-o:before {content: \"\\f274\";}\n\ -.fa-industry:before {content: \"\\f275\";}\n\ -.fa-map-pin:before {content: \"\\f276\";}\n\ -.fa-map-signs:before {content: \"\\f277\";}\n\ -.fa-map-o:before {content: \"\\f278\";}\n\ -.fa-map:before {content: \"\\f279\";}\n\ -.fa-commenting:before {content: \"\\f27a\";}\n\ -.fa-commenting-o:before {content: \"\\f27b\";}\n\ -.fa-houzz:before {content: \"\\f27c\";}\n\ -.fa-vimeo:before {content: \"\\f27d\";}\n\ -.fa-black-tie:before {content: \"\\f27e\";}\n\ -.fa-fonticons:before {content: \"\\f280\";}\n\ -.fa-reddit-alien:before {content: \"\\f281\";}\n\ -.fa-edge:before {content: \"\\f282\";}\n\ -.fa-credit-card-alt:before {content: \"\\f283\";}\n\ -.fa-codiepie:before {content: \"\\f284\";}\n\ -.fa-modx:before {content: \"\\f285\";}\n\ -.fa-fort-awesome:before {content: \"\\f286\";}\n\ -.fa-usb:before {content: \"\\f287\";}\n\ -.fa-product-hunt:before {content: \"\\f288\";}\n\ -.fa-mixcloud:before {content: \"\\f289\";}\n\ -.fa-scribd:before {content: \"\\f28a\";}\n\ -.fa-pause-circle:before {content: \"\\f28b\";}\n\ -.fa-pause-circle-o:before {content: \"\\f28c\";}\n\ -.fa-stop-circle:before {content: \"\\f28d\";}\n\ -.fa-stop-circle-o:before {content: \"\\f28e\";}\n\ -.fa-shopping-bag:before {content: \"\\f290\";}\n\ -.fa-shopping-basket:before {content: \"\\f291\";}\n\ -.fa-hashtag:before {content: \"\\f292\";}\n\ -.fa-bluetooth:before {content: \"\\f293\";}\n\ -.fa-bluetooth-b:before {content: \"\\f294\";}\n\ -.fa-percent:before {content: \"\\f295\";}\n\ -.fa-gitlab:before {content: \"\\f296\";}\n\ -.fa-wpbeginner:before {content: \"\\f297\";}\n\ -.fa-wpforms:before {content: \"\\f298\";}\n\ -.fa-envira:before {content: \"\\f299\";}\n\ -.fa-universal-access:before {content: \"\\f29a\";}\n\ -.fa-wheelchair-alt:before {content: \"\\f29b\";}\n\ -.fa-question-circle-o:before {content: \"\\f29c\";}\n\ -.fa-blind:before {content: \"\\f29d\";}\n\ -.fa-audio-description:before {content: \"\\f29e\";}\n\ -.fa-volume-control-phone:before {content: \"\\f2a0\";}\n\ -.fa-braille:before {content: \"\\f2a1\";}\n\ -.fa-assistive-listening-systems:before {content: \"\\f2a2\";}\n\ -.fa-asl-interpreting:before, .fa-american-sign-language-interpreting:before {content: \"\\f2a3\";}\n\ -.fa-deafness:before, .fa-hard-of-hearing:before, .fa-deaf:before {content: \"\\f2a4\";}\n\ -.fa-glide:before {content: \"\\f2a5\";}\n\ -.fa-glide-g:before {content: \"\\f2a6\";}\n\ -.fa-signing:before, .fa-sign-language:before {content: \"\\f2a7\";}\n\ -.fa-low-vision:before {content: \"\\f2a8\";}\n\ -.fa-viadeo:before {content: \"\\f2a9\";}\n\ -.fa-viadeo-square:before {content: \"\\f2aa\";}\n\ -.fa-snapchat:before {content: \"\\f2ab\";}\n\ -.fa-snapchat-ghost:before {content: \"\\f2ac\";}\n\ -.fa-snapchat-square:before {content: \"\\f2ad\";}\n\ -.fa-pied-piper:before {content: \"\\f2ae\";}\n\ -.fa-first-order:before {content: \"\\f2b0\";}\n\ -.fa-yoast:before {content: \"\\f2b1\";}\n\ -.fa-themeisle:before {content: \"\\f2b2\";}\n\ -.fa-google-plus-circle:before, .fa-google-plus-official:before {content: \"\\f2b3\";}\n\ -.fa-fa:before, .fa-font-awesome:before {content: \"\\f2b4\";}\n\ -.fa-handshake-o:before {content: \"\\f2b5\";}\n\ -.fa-envelope-open:before {content: \"\\f2b6\";}\n\ -.fa-envelope-open-o:before {content: \"\\f2b7\";}\n\ -.fa-linode:before {content: \"\\f2b8\";}\n\ -.fa-address-book:before {content: \"\\f2b9\";}\n\ -.fa-address-book-o:before {content: \"\\f2ba\";}\n\ -.fa-vcard:before, .fa-address-card:before {content: \"\\f2bb\";}\n\ -.fa-vcard-o:before, .fa-address-card-o:before {content: \"\\f2bc\";}\n\ -.fa-user-circle:before {content: \"\\f2bd\";}\n\ -.fa-user-circle-o:before {content: \"\\f2be\";}\n\ -.fa-user-o:before {content: \"\\f2c0\";}\n\ -.fa-id-badge:before {content: \"\\f2c1\";}\n\ -.fa-drivers-license:before, .fa-id-card:before {content: \"\\f2c2\";}\n\ -.fa-drivers-license-o:before, .fa-id-card-o:before {content: \"\\f2c3\";}\n\ -.fa-quora:before {content: \"\\f2c4\";}\n\ -.fa-free-code-camp:before {content: \"\\f2c5\";}\n\ -.fa-telegram:before {content: \"\\f2c6\";}\n\ -.fa-thermometer-4:before, .fa-thermometer:before, .fa-thermometer-full:before {content: \"\\f2c7\";}\n\ -.fa-thermometer-3:before, .fa-thermometer-three-quarters:before {content: \"\\f2c8\";}\n\ -.fa-thermometer-2:before, .fa-thermometer-half:before {content: \"\\f2c9\";}\n\ -.fa-thermometer-1:before, .fa-thermometer-quarter:before {content: \"\\f2ca\";}\n\ -.fa-thermometer-0:before, .fa-thermometer-empty:before {content: \"\\f2cb\";}\n\ -.fa-shower:before {content: \"\\f2cc\";}\n\ -.fa-bathtub:before, .fa-s15:before, .fa-bath:before {content: \"\\f2cd\";}\n\ -.fa-podcast:before {content: \"\\f2ce\";}\n\ -.fa-window-maximize:before {content: \"\\f2d0\";}\n\ -.fa-window-minimize:before {content: \"\\f2d1\";}\n\ -.fa-window-restore:before {content: \"\\f2d2\";}\n\ -.fa-times-rectangle:before, .fa-window-close:before {content: \"\\f2d3\";}\n\ -.fa-times-rectangle-o:before, .fa-window-close-o:before {content: \"\\f2d4\";}\n\ -.fa-bandcamp:before {content: \"\\f2d5\";}\n\ -.fa-grav:before {content: \"\\f2d6\";}\n\ -.fa-etsy:before {content: \"\\f2d7\";}\n\ -.fa-imdb:before {content: \"\\f2d8\";}\n\ -.fa-ravelry:before {content: \"\\f2d9\";}\n\ -.fa-eercast:before {content: \"\\f2da\";}\n\ -.fa-microchip:before {content: \"\\f2db\";}\n\ -.fa-snowflake-o:before {content: \"\\f2dc\";}\n\ -.fa-superpowers:before {content: \"\\f2dd\";}\n\ -.fa-wpexplorer:before {content: \"\\f2de\";}\n\ -.fa-meetup:before {content: \"\\f2e0\";}\n\ -.fa::before {\n\ - font-family: FontAwesome;\n\ - font-weight: 400;\n\ - font-style: normal;\n\ - -webkit-font-smoothing: antialiased;\n\ - text-decoration: inherit;\n\ - speak: none;\n\ - display: inline-block;\n\ - font-size: 13px;\n\ - visibility: visible;\n\ -}\n\ -:root:not(.shortcut-icons) #shortcuts .fa::before {\n\ - display: none;\n\ -}\n\ -:root.shortcut-icons #shortcuts .fa::before {\n\ - font-size: 15px !important;\n\ - margin-top: -3px !important;\n\ - position: relative;\n\ - top: 1px;\n\ -}\n\ -:root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n\ - font-size: 0;\n\ - visibility: hidden;\n\ -}\n\ -:root.shortcut-icons .shortcut.brackets-wrap::after,\n\ -:root.shortcut-icons .shortcut.brackets-wrap::before {\n\ - display: none;\n\ -}\n\ -:root.shortcut-icons #shortcuts a .fa,\n\ -.menu-button .fa,\n\ -.hide-reply-button .fa,\n\ -.hide-thread-button .fa {\n\ - display: inline;\n\ -}\n\ -.fa-spin::before {\n\ - -webkit-animation:spin 2s infinite linear;\n\ - -moz-animation:spin 2s infinite linear;\n\ - -o-animation:spin 2s infinite linear;\n\ - animation:spin 2s infinite linear;\n\ -}\n\ -@-moz-keyframes spin {\n\ - 0% {-moz-transform:rotate(0deg);}\n\ - 100% {-moz-transform:rotate(359deg);}\n\ -}\n\ -@-webkit-keyframes spin {\n\ - 0% {-webkit-transform:rotate(0deg);}\n\ - 100% {-webkit-transform:rotate(359deg);}\n\ -}\n\ -@keyframes spin {\n\ - 0% {transform:rotate(0deg);}\n\ - 100% {transform:rotate(359deg);}\n\ -}\n\ -/* General */\n\ -.dialog {\n\ - border: 1px solid;\n\ - display: block;\n\ - background-color: inherit;\n\ -}\n\ -.dialog:not(#qr):not(#thread-watcher):not(#header-bar) {\n\ - box-shadow: 0 1px 2px rgba(0, 0, 0, .15);\n\ -}\n\ -#qr,\n\ -#thread-watcher {\n\ - box-shadow: -1px 2px 2px rgba(0, 0, 0, 0.25);\n\ -}\n\ -.captcha-img,\n\ -.field {\n\ - background-color: #FFF;\n\ - border: 1px solid #CCC;\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - color: #333;\n\ - font: 13px sans-serif;\n\ - outline: none;\n\ - transition: color .25s, border-color .25s;\n\ -}\n\ -.field::-moz-placeholder {\n\ - color: #AAA;\n\ - font-size: 13px;\n\ - opacity: 1;\n\ -}\n\ -.captch-img:hover,\n\ -.field:hover {\n\ - border-color: #999;\n\ -}\n\ -.field:hover, .field:focus, .field.focus {\n\ - color: #000;\n\ -}\n\ -.field[disabled] {\n\ - background-color: #F2F2F2;\n\ - color: #888;\n\ -}\n\ -.field::-webkit-search-decoration {\n\ - display: none;\n\ -}\n\ -.move {\n\ - cursor: move;\n\ - overflow: hidden;\n\ -}\n\ -label {\n\ - cursor: pointer;\n\ -}\n\ -a[href=\"javascript:;\"] {\n\ - text-decoration: none;\n\ -}\n\ -.warning {\n\ - color: red;\n\ -}\n\ -:root.sw-yotsuba #boardNavDesktop, :root.sw-yotsuba #boardNavMobile {\n\ - display: none !important;\n\ -}\n\ -:root.hide-bottom-board-list $site$boardListBottom {\n\ - display: none;\n\ -}\n\ -body.hasDropDownNav{\n\ - margin-top: 5px;\n\ -}\n\ -:root:not(.keyboard-focus) a {\n\ - outline: none;\n\ -}\n\ -.painted {\n\ - border-radius: 3px;\n\ - padding: 0px 2px;\n\ -}\n\ -[hidden] {\n\ - display: none !important;\n\ -}\n\ -/* 4chan style fixes */\n\ -/* overrides 4chan CSS on div.opContainer, div.op */\n\ -:root.sw-yotsuba .opContainer, :root.sw-yotsuba .op {\n\ - display: block;\n\ - overflow: visible;\n\ -}\n\ -:root.sw-yotsuba .reply > .file > .fileText {\n\ - margin: 0 20px;\n\ -}\n\ -:root.sw-yotsuba #arc-list span.quote {\n\ - color: #789922;\n\ -}\n\ -:root.sw-yotsuba .fileText a {\n\ - unicode-bidi: -moz-isolate;\n\ - unicode-bidi: -webkit-isolate;\n\ -}\n\ -:root.sw-yotsuba #g-recaptcha {\n\ - min-height: 78px;\n\ - height: auto;\n\ -}\n\ -:root.sw-yotsuba:not(.js-enabled) #postForm {\n\ - display: table;\n\ -}\n\ -:root.sw-yotsuba #captchaContainerAlt td:nth-child(2) {\n\ - display: table-cell !important;\n\ -}\n\ -:root.sw-yotsuba canvas#tegaki-canvas {\n\ - background: none;\n\ -}\n\ -/* Disable obnoxious captcha fade-in. */\n\ -:root.sw-yotsuba > body > div:last-of-type {\n\ - transition: none !important;\n\ -}\n\ -/* Fix captcha scrolling to top of page. */\n\ -:root.sw-yotsuba > body > div[style*=\" top: -10000px;\"] {\n\ - visibility: hidden !important;\n\ -}\n\ -/* Make long filenames wrap properly: https://github.com/ccd0/4chan-x/issues/1082 */\n\ -:root.sw-yotsuba .post > .file {\n\ - /* currently nonstandard but may be added: https://lists.w3.org/Archives/Public/www-style/2016Mar/0352.html, https://bugzilla.mozilla.org/show_bug.cgi?id=1296042 */\n\ - word-break: break-word;\n\ -}\n\ -:root.sw-yotsuba:not(.ua-webkit):not(.ua-blink) .fileText {\n\ - word-wrap: break-word;\n\ - max-width: calc(100vw - 90px);\n\ -}\n\ -:root.sw-yotsuba > body.is_catalog .thread > a > img {\n\ - display: inline-block;\n\ -}\n\ -/* Links to NSFW boards */\n\ -:root.sw-yotsuba .nwsb {\n\ - display: inline;\n\ -}\n\ -:root.sw-yotsuba .fileText {\n\ - max-width: auto;\n\ - white-space: normal;\n\ -}\n\ -/* Ads */\n\ -:root.sw-yotsuba .ad-cnt > *, :root.sw-yotsuba .adg-rects > *, :root.sw-yotsuba .bsa-cnt {\n\ - height: auto !important;\n\ -}\n\ -:root.sw-yotsuba:not(.ads-loaded) hr.abovePostForm,\n\ -:root.sw-yotsuba:not(.ads-loaded) .adg-rects > hr,\n\ -:root.sw-yotsuba #adg-ol + hr,\n\ -:root.sw-yotsuba .danbo-slot:empty {\n\ - display: none;\n\ -}\n\ -:root.sw-yotsuba .adg-rects {\n\ - margin: 0;\n\ - font-size: 0;\n\ -}\n\ -:root.sw-yotsuba div.center[style] {\n\ - display: none !important;\n\ -}\n\ -/* Tinyboard / vichan conflicts */\n\ -#menu > .hide-thread-link {\n\ - width: auto;\n\ - height: auto;\n\ - overflow: visible;\n\ - background-image: none;\n\ -}\n\ -#menu label.entry {\n\ - display: block;\n\ -}\n\ -#fourchanx-settings label {\n\ - display: inline;\n\ -}\n\ -.intro a[href=\"javascript:;\"],\n\ -#menu a {\n\ - margin: 0;\n\ -}\n\ -.gal-buttons.gal-buttons a {\n\ - font-size: inherit;\n\ -}\n\ -:root.sw-tinyboard.fixed.top-header:not(.autohide) .boardlist,\n\ -:root.sw-tinyboard.fixed.top-header:not(.autohide) .bar.top {\n\ - position: static;\n\ -}\n\ -:root.sw-tinyboard.fixed.top-header:not(.autohide) div.pages.top {\n\ - top: auto;\n\ - bottom: 0;\n\ -}\n\ -:root.sw-tinyboard.fixed.top-header.autohide .boardlist,\n\ -:root.sw-tinyboard.fixed.top-header.autohide .bar.top {\n\ - z-index: 3;\n\ -}\n\ -/* Tinyboard site style conflicts */\n\ -:root[data-host=\"fufufu.moe\"].fixed.top-header:not(.autohide) div.pages.top {\n\ - top: 26px;\n\ - bottom: auto;\n\ -}\n\ -:root[data-host=\"merorin.com\"].fixed.top-header:not(.autohide) span.settings {\n\ - top: 26px;\n\ -}\n\ -:root[data-host=\"fufufu.moe\"]:not(.fixed) #header-bar {\n\ - margin-top: 38px;\n\ -}\n\ -:root[data-host=\"lainchan.org\"]:not(.fixed) #header-bar {\n\ - margin-top: 17px;\n\ -}\n\ -:root[data-host=\"smuglo.li\"]:not(.fixed) #header-bar {\n\ - margin-top: 8px;\n\ -}\n\ -/* Anti-autoplay */\n\ -audio.controls-added {\n\ - display: block;\n\ - margin: auto;\n\ - white-space: normal;\n\ -}\n\ -:root.anti-autoplay div.embed {\n\ - position: static;\n\ - width: auto;\n\ - height: auto;\n\ - text-align: center;\n\ -}\n\ -:root.anti-autoplay .autoplay-removed {\n\ - visibility: visible !important;\n\ - min-width: 640px;\n\ - min-height: 360px;\n\ -}\n\ -/* fixed, z-index */\n\ -#overlay,\n\ -#qp, #ihover,\n\ -#navlinks, .fixed #header-bar,\n\ -:root.float #updater,\n\ -:root.float #thread-stats,\n\ -#qr {\n\ - position: fixed;\n\ -}\n\ -#overlay {\n\ - z-index: 999;\n\ -}\n\ -#qp, #ihover {\n\ - z-index: 60;\n\ -}\n\ -#menu, .gal-buttons {\n\ - z-index: 50;\n\ -}\n\ -#updater, #thread-stats {\n\ - z-index: 40;\n\ -}\n\ -:root.fixed #header-bar, #notifications {\n\ - z-index: 35;\n\ -}\n\ -#a-gallery {\n\ - z-index: 30;\n\ -}\n\ -#navlinks {\n\ - z-index: 25;\n\ -}\n\ -#qr {\n\ - z-index: 20;\n\ -}\n\ -#embedding {\n\ - z-index: 11;\n\ -}\n\ -:root.fixed-watcher #thread-watcher {\n\ - z-index: 10;\n\ -}\n\ -:root.fixed:not(.gallery-open) #header-bar:not(:hover) {\n\ - z-index: 8;\n\ -}\n\ -#thread-watcher {\n\ - z-index: 5;\n\ -}\n\ -/* Header */\n\ -.fixed.top-header body {\n\ - padding-top: 2em;\n\ -}\n\ -.fixed.bottom-header body {\n\ - padding-bottom: 2em;\n\ -}\n\ -.fixed #header-bar {\n\ - right: 0;\n\ - left: 0;\n\ - padding: 3px 4px 4px;\n\ - font-size: 12px;\n\ -}\n\ -.fixed.top-header #header-bar {\n\ - top: 0;\n\ -}\n\ -.fixed.bottom-header #header-bar {\n\ - bottom: 0;\n\ -}\n\ -#header-bar {\n\ - border-width: 0;\n\ - transition: all .1s .05s ease-in-out;\n\ -}\n\ -:root.fixed #header-bar {\n\ - box-shadow: -5px 1px 10px rgba(0, 0, 0, 0.20);\n\ -}\n\ -:root.centered-links #shortcuts {\n\ - width: 300px;\n\ - text-align: right;\n\ -}\n\ -:root.centered-links #header-bar {\n\ - text-align: center;\n\ -}\n\ -#custom-board-list {\n\ - font-size: 13px;\n\ - vertical-align: middle;\n\ -}\n\ -#full-board-list {\n\ - vertical-align: middle;\n\ -}\n\ -:root.centered-links #custom-board-list {\n\ - position: relative;\n\ - left: 150px;\n\ -}\n\ -.fixed.top-header #header-bar {\n\ - border-bottom-width: 1px;\n\ -}\n\ -.fixed.bottom-header #header-bar {\n\ - box-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\n\ - border-top-width: 1px;\n\ -}\n\ -.fixed.bottom-header #header-bar .menu-button i {\n\ - border-top: none;\n\ - border-bottom: 6px solid;\n\ -}\n\ -.fixed #header-bar.autohide:not(:hover) {\n\ - box-shadow: none;\n\ - transition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n\ -}\n\ -.fixed.top-header #header-bar.autohide:not(:hover) {\n\ - margin-bottom: -1em;\n\ - -webkit-transform: translateY(-100%);\n\ - transform: translateY(-100%);\n\ -}\n\ -.fixed.bottom-header #header-bar.autohide:not(:hover) {\n\ - -webkit-transform: translateY(100%);\n\ - transform: translateY(100%);\n\ -}\n\ -#scroll-marker {\n\ - left: 0;\n\ - right: 0;\n\ - height: 10px;\n\ - position: absolute;\n\ -}\n\ -#header-bar:not(.autohide) #scroll-marker {\n\ - pointer-events: none;\n\ -}\n\ -#header-bar #scroll-marker {\n\ - display: none;\n\ -}\n\ -.fixed #header-bar #scroll-marker {\n\ - display: block;\n\ -}\n\ -.fixed.top-header #header-bar #scroll-marker {\n\ - top: 100%;\n\ -}\n\ -.fixed.bottom-header #header-bar #scroll-marker {\n\ - bottom: 100%;\n\ -}\n\ -#board-list a, #shortcuts a:not(.entry) {\n\ - text-decoration: none;\n\ - padding: 1px;\n\ -}\n\ -#shortcuts:empty {\n\ - display: none;\n\ -}\n\ -.brackets-wrap::before {\n\ - content: \"\\00a0[\";\n\ -}\n\ -.brackets-wrap::after {\n\ - content: \"]\\00a0\";\n\ -}\n\ -.dead-thread,\n\ -.disabled:not(.replies-quoting-you) {\n\ - opacity: .45;\n\ -}\n\ -#shortcuts {\n\ - float: right;\n\ -}\n\ -:root.autohiding-scrollbar #shortcuts {\n\ - margin-right: 12px;\n\ -}\n\ -.shortcut {\n\ - margin-left: 3px;\n\ - vertical-align: middle;\n\ -}\n\ -:root.shortcut-icons .native-settings {\n\ - font-size: 0;\n\ - color: transparent;\n\ - display: inline-block;\n\ - vertical-align: top;\n\ - height: 12px;\n\ - width: 14px;\n\ - background: url('//s.4cdn.org/image/favicon.ico') 0px -1px no-repeat;\n\ -}\n\ -#navbotright,\n\ -#navtopright {\n\ - display: none;\n\ -}\n\ -#toggleMsgBtn {\n\ - display: none !important;\n\ -}\n\ -.current,\n\ -:root.sw-yotsuba div#boardNavDesktopFoot a.current {\n\ - font-weight: bold;\n\ -}\n\ -@media (min-width: 1300px) {\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #header-bar {\n\ - white-space: nowrap;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #board-list {\n\ - -webkit-flex: auto;\n\ - flex: auto;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) .hide-board-list-container {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - margin-right: 5px;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList {\n\ - -webkit-flex: auto;\n\ - flex: auto;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - width: 0px; /* XXX Fixes Edge not shrinking the board list below default size when needed */\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > a,\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span:not(.space):not(.spacer) {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - padding: .17em;\n\ - margin: -.17em -.32em;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span {\n\ - pointer-events: none;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span.space {\n\ - -webkit-flex: 0 .63 .63em;\n\ - flex: 0 .63 .63em;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span.spacer {\n\ - -webkit-flex: 0 .38 .38em;\n\ - flex: 0 .38 .38em;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #shortcuts {\n\ - float: initial;\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - }\n\ -}\n\ -/* 4chan X link brackets */\n\ -.brackets-wrap::before {\n\ - content: \"[\";\n\ -}\n\ -.brackets-wrap::after {\n\ - content: \"]\";\n\ -}\n\ -/* Notifications */\n\ -#notifications {\n\ - position: fixed;\n\ - top: 0;\n\ - height: 0;\n\ - text-align: center;\n\ - right: 0;\n\ - left: 0;\n\ - visibility: visible;\n\ -}\n\ -#notifications:empty {\n\ - display: none;\n\ -}\n\ -:root.fixed.top-header:not(.gallery-open) #header-bar #notifications,\n\ -:root.fixed.top-header #header-bar.autohide #notifications {\n\ - position: absolute;\n\ - top: 100%;\n\ -}\n\ -.notification {\n\ - color: #FFF;\n\ - font-weight: 700;\n\ - text-shadow: 0 1px 2px rgba(0, 0, 0, .5);\n\ - box-shadow: 0 1px 2px rgba(0, 0, 0, .15);\n\ - border-radius: 2px;\n\ - margin: 1px auto;\n\ - width: 550px;\n\ - max-width: 100%;\n\ - position: relative;\n\ - transition: all .25s ease-in-out;\n\ -}\n\ -.notification.error {\n\ - background-color: hsla(0, 100%, 38%, .9);\n\ -}\n\ -.notification.warning {\n\ - background-color: hsla(36, 100%, 38%, .9);\n\ -}\n\ -.notification.info {\n\ - background-color: hsla(200, 100%, 38%, .9);\n\ -}\n\ -.notification.success {\n\ - background-color: hsla(104, 100%, 38%, .9);\n\ -}\n\ -.notification a {\n\ - color: white;\n\ -}\n\ -.notification > .close {\n\ - padding: 7px;\n\ - top: 0px;\n\ - right: 5px;\n\ - position: absolute;\n\ -}\n\ -.notification > .fa-times::before {\n\ - font-size: 11px !important;\n\ -}\n\ -.message {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - padding: 6px 20px;\n\ - max-height: 200px;\n\ - width: 100%;\n\ - overflow: auto;\n\ - white-space: pre-line;\n\ -}\n\ -.message a {\n\ - text-decoration: underline;\n\ -}\n\ -:root.tainted .report-error {\n\ - display: none;\n\ -}\n\ -/* Settings */\n\ -:root.fourchan-x body {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ -}\n\ -#overlay {\n\ - background-color: rgba(0, 0, 0, .5);\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - top: 0;\n\ - left: 0;\n\ - height: 100%;\n\ - width: 100%;\n\ -}\n\ -#fourchanx-settings {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - box-shadow: 0 0 15px rgba(0, 0, 0, .15);\n\ - height: 600px;\n\ - max-height: 100%;\n\ - width: 900px;\n\ - max-width: 100%;\n\ - margin: auto;\n\ - padding: 5px;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: column;\n\ - flex-direction: column;\n\ -}\n\ -#fourchanx-settings > nav {\n\ - padding: 2px 2px 8px;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ -}\n\ -#fourchanx-settings > nav a {\n\ - text-decoration: underline;\n\ -}\n\ -#fourchanx-settings > nav a.close {\n\ - text-decoration: none;\n\ - padding: 0 2px;\n\ - margin: 0;\n\ -}\n\ -.section-container {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ - position: relative;\n\ - overflow: auto;\n\ - padding-right: 5px;\n\ - overscroll-behavior: contain;\n\ -}\n\ -.sections-list {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ -}\n\ -.export, .import, .reset {\n\ - cursor: pointer;\n\ - text-decoration: none !important;\n\ -}\n\ -.tab-selected {\n\ - font-weight: 700;\n\ -}\n\ -.section-sauce ul,\n\ -.section-advanced ul {\n\ - list-style: none;\n\ - margin: 0;\n\ -}\n\ -.section-sauce ul {\n\ - padding: 8px;\n\ -}\n\ -.section-advanced ul {\n\ - padding: 0px;\n\ -}\n\ -.section-sauce li,\n\ -.section-advanced li {\n\ - padding-left: 4px;\n\ -}\n\ -.section-main ul {\n\ - margin: 0;\n\ - padding: 0 0 0 16px;\n\ -}\n\ -.section-main li {\n\ - white-space: pre-line;\n\ - list-style: disc;\n\ -}\n\ -.section-main li:not(:first-of-type) {\n\ - margin-top: 4px;\n\ -}\n\ -.section-main label {\n\ - text-decoration: underline;\n\ -}\n\ -div[data-checked=\"false\"] > .suboption-list {\n\ - display: none;\n\ -}\n\ -.suboption-list {\n\ - position: relative;\n\ -}\n\ -.suboption-list::before {\n\ - content: \"\";\n\ - display: inline-block;\n\ - position: absolute;\n\ - left: .7em;\n\ - width: 0;\n\ - height: 100%;\n\ - border-left: 1px solid;\n\ -}\n\ -.suboption-list > div {\n\ - position: relative;\n\ - padding-left: 1.4em;\n\ -}\n\ -.suboption-list > div::before {\n\ - content: \"\";\n\ - display: inline-block;\n\ - position: absolute;\n\ - left: .7em;\n\ - width: .7em;\n\ - height: .6em;\n\ - border-left: 1px solid;\n\ - border-bottom: 1px solid;\n\ -}\n\ -#fourchanx-settings .section-main p {\n\ - margin: .5em 0 0;\n\ -}\n\ -.section-filter ul {\n\ - padding: 0;\n\ -}\n\ -.section-filter li {\n\ - margin: 10px 40px;\n\ - list-style: disc;\n\ -}\n\ -.section-filter textarea {\n\ - height: 500px;\n\ -}\n\ -.section-main a, .section-filter a, .section-advanced a {\n\ - text-decoration: underline;\n\ -}\n\ -#sauce-doc-expand:not(:checked) ~ #sauce-doc {\n\ - max-height: 130px;\n\ - overflow: auto;\n\ -}\n\ -#sauce-doc > label {\n\ - float: right;\n\ - margin: 0 5px;\n\ -}\n\ -/* XXX for OneeChan */\n\ -#sauce-doc-expand + .riceCheck {\n\ - display: none;\n\ -}\n\ -.section-sauce textarea {\n\ - height: 430px;\n\ -}\n\ -.section-advanced .field[name=\"boardnav\"] {\n\ - width: 100%;\n\ -}\n\ -.section-advanced textarea {\n\ - height: 150px;\n\ -}\n\ -.section-advanced textarea[name=\"archiveLists\"],\n\ -.section-advanced textarea[name=\"externalCatalogURLs\"],\n\ -.section-advanced textarea[name=\"knownBanners\"] {\n\ - height: 75px;\n\ -}\n\ -.section-advanced .archive-cell {\n\ - min-width: 160px;\n\ - text-align: center;\n\ -}\n\ -.section-advanced #archive-board-select {\n\ - position: absolute;\n\ -}\n\ -.section-advanced .note {\n\ - font-size: 0.8em;\n\ - font-style: italic;\n\ - margin-left: 10px;\n\ -}\n\ -.section-advanced .note code {\n\ - font-style: normal;\n\ - font-size: 11px;\n\ -}\n\ -.favicon-preview > img {\n\ - vertical-align: middle;\n\ -}\n\ -.favicon-preview > img:nth-of-type(3n+1) {\n\ - margin-left: 4px;\n\ -}\n\ -.section-keybinds .field {\n\ - font-family: monospace;\n\ -}\n\ -#fourchanx-settings fieldset {\n\ - border: 1px solid;\n\ - border-radius: 3px;\n\ - padding: 0.35em 0.625em 0.75em;\n\ - margin: 0px 2px;\n\ -}\n\ -#fourchanx-settings legend {\n\ - font-weight: 700;\n\ - color: inherit;\n\ -}\n\ -#fourchanx-settings textarea {\n\ - font-family: monospace;\n\ - width: 100%;\n\ - resize: vertical;\n\ -}\n\ -#fourchanx-settings code {\n\ - color: #000;\n\ - background-color: #FFF;\n\ - padding: 0 2px;\n\ -}\n\ -#fourchanx-settings th {\n\ - text-align: center;\n\ - font-weight: bold;\n\ -}\n\ -#fourchanx-settings p {\n\ - margin: 1em 0px;\n\ -}\n\ -#fourchanx-settings table {\n\ - margin: auto;\n\ -}\n\ -/* Index */\n\ -:root.index-loading .navLinks:not(.json-index),\n\ -:root.index-loading .board:not(.json-index),\n\ -:root.index-loading .pagelist:not(.json-index),\n\ -:root.infinite-mode .pagelist,\n\ -:root.all-pages-mode .pagelist,\n\ -:root.catalog-mode .pagelist,\n\ -:root:not(.catalog-mode) .indexlink,\n\ -:root.catalog-mode .cataloglink,\n\ -:root:not(.catalog-mode) #hidden-label,\n\ -:root:not(.catalog-mode) #index-size {\n\ - display: none;\n\ -}\n\ -#index-search {\n\ - padding-right: 1.5em;\n\ - width: 100px;\n\ - transition: color .25s, border-color .25s, width .25s;\n\ -}\n\ -#index-search:focus,\n\ -#index-search[data-searching] {\n\ - width: 200px;\n\ -}\n\ -#index-search-clear {\n\ - color: gray;\n\ - display: inline-block;\n\ - position: relative;\n\ - left: -1em;\n\ - width: 0;\n\ -}\n\ -/* ``::-webkit-*'' selectors break selector lists on Firefox. */\n\ -#index-search::-webkit-search-cancel-button {\n\ - display: none;\n\ -}\n\ -#index-search:not([data-searching]) + #index-search-clear {\n\ - display: none;\n\ -}\n\ -#index-options {\n\ - float: right;\n\ -}\n\ -#lastlong-options {\n\ - display: inline-block;\n\ - vertical-align: middle;\n\ - height: 28px;\n\ - margin: -14px 0;\n\ -}\n\ -#lastlong-options > input {\n\ - padding: 0;\n\ - border: 0 !important;\n\ - text-align: center;\n\ - background: transparent;\n\ - display: block;\n\ - font-size: 12px;\n\ - height: 12px;\n\ - width: 30px;\n\ - margin: 1px 0;\n\ -}\n\ -.summary {\n\ - text-decoration: none;\n\ -}\n\ -/* Catalog */\n\ -:root.catalog-mode .board {\n\ - text-align: center;\n\ -}\n\ -.catalog-thread {\n\ - display: inline-block;\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - border: 1px solid transparent;\n\ - word-wrap: break-word;\n\ - vertical-align: top;\n\ - position: relative;\n\ -}\n\ -/* overrides 4chan CSS on div.thread */\n\ -.catalog-thread.catalog-thread {\n\ - margin: 2px;\n\ -}\n\ -.catalog-small > .catalog-thread {\n\ - width: 165px;\n\ - height: 320px;\n\ -}\n\ -.catalog-large > .catalog-thread {\n\ - width: 270px;\n\ - height: 410px;\n\ -}\n\ -:root.catalog-hover-expand .catalog-thread:hover {\n\ - z-index: 1;\n\ -}\n\ -.catalog-container {\n\ - position: absolute;\n\ - top: -4px;\n\ - left: 0;\n\ - right: 0;\n\ - bottom: 0;\n\ -}\n\ -.catalog-container:not(:hover),\n\ -:root:not(.catalog-hover-expand) .catalog-container {\n\ - overflow: hidden;\n\ -}\n\ -.catalog-post {\n\ - position: absolute;\n\ - top: 4px;\n\ - left: 0;\n\ - right: 0;\n\ - border: 1px solid transparent;\n\ - padding-top: 20px;\n\ -}\n\ -/* overrides inline CSS from Index.cb.hoverAdjust */\n\ -:root:not(.catalog-hover-expand) .catalog-post {\n\ - left: 0 !important;\n\ - right: 0 !important;\n\ -}\n\ -/* overrides 4chan CSS on div.post */\n\ -.catalog-post.catalog-post {\n\ - margin: -21px -1px -1px;\n\ - overflow: visible;\n\ -}\n\ -.catalog-thread.noFile > * > .catalog-post {\n\ - margin-top: -7px;\n\ - padding-top: 6px;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover > .catalog-post {\n\ - margin-left: -61px;\n\ - margin-right: -61px;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover > * > :not(.catalog-replies) {\n\ - padding-left: 2px;\n\ - padding-right: 2px;\n\ -}\n\ -.catalog-link {\n\ - display: block;\n\ - position: relative;\n\ -}\n\ -.catalog-thumb {\n\ - border-radius: 2px;\n\ - box-shadow: 0 0 5px rgba(0, 0, 0, .25);\n\ - vertical-align: top;\n\ -}\n\ -.catalog-thumb.spoiler-file {\n\ - width: 100px;\n\ - height: 100px;\n\ -}\n\ -.catalog-thumb.deleted-file {\n\ - width: 127px;\n\ - height: 13px;\n\ - padding: 20px 11px;\n\ -}\n\ -.catalog-thumb.no-file {\n\ - width: 77px;\n\ - height: 13px;\n\ - padding: 20px 36px;\n\ -}\n\ -.catalog-icons > img,\n\ -.catalog-stats > .menu-button {\n\ - width: 1em;\n\ - height: 1em;\n\ - margin: 0;\n\ - vertical-align: text-top;\n\ - padding-left: 2px;\n\ -}\n\ -.catalog-stats > .menu-button {\n\ - font-weight: normal;\n\ -}\n\ -.catalog-stats > .menu-button > i::before {\n\ - line-height: 11px;\n\ -}\n\ -.catalog-stats {\n\ - font-size: 10px;\n\ - font-weight: 700;\n\ - padding-top: 2px;\n\ -}\n\ -.catalog-stats > [title] {\n\ - cursor: help;\n\ -}\n\ -.catalog-post > .postMessage {\n\ - margin: 0;\n\ - padding-bottom: .3em;\n\ -}\n\ -.catalog-container:not(:hover) > * > .file,\n\ -.catalog-container:not(:hover) > * > .postInfo > :not(.subject),\n\ -.catalog-container:not(:hover) > * > .catalog-replies,\n\ -.catalog-container:not(:hover) .extra-linebreak,\n\ -.catalog-container:not(:hover) .abbr,\n\ -:root:not(.catalog-hover-expand) .catalog-container > * > .file,\n\ -:root:not(.catalog-hover-expand) .catalog-container > * > .postInfo > :not(.subject),\n\ -:root:not(.catalog-hover-expand) .catalog-container > * > .catalog-replies,\n\ -:root:not(.catalog-hover-expand) .catalog-container .extra-linebreak,\n\ -:root:not(.catalog-hover-expand) .catalog-container .abbr,\n\ -.catalog-thread > .catalog-container > :not(.catalog-post),\n\ -.catalog-post > .file > :not(.fileText),\n\ -.catalog-post > * > .fileText > :not(:first-child),\n\ -.catalog-post > .postInfo > :not(.subject):not(.nameBlock):not(.dateTime),\n\ -.catalog-post > .postInfo > .nameBlock > .contact-links,\n\ -.catalog-post > * > * > .posteruid,\n\ -.catalog-post > * > * > .postJumper,\n\ -:root.bottom-backlinks .catalog-post > .container,\n\ -.post:not(.catalog-post) > .catalog-link,\n\ -.post:not(.catalog-post) > .catalog-stats,\n\ -.post:not(.catalog-post) > .catalog-replies {\n\ - display: none;\n\ -}\n\ -.catalog-post > .file {\n\ - position: absolute;\n\ - left: 0;\n\ - right: 0;\n\ - top: 0;\n\ - min-height: 20px;\n\ - background-color: inherit;\n\ -}\n\ -.catalog-post > * > .fileText {\n\ - position: relative;\n\ - padding: 2px;\n\ - background-color: inherit;\n\ -}\n\ -.catalog-small .catalog-post > * .fileText {\n\ - font-size: 10px;\n\ -}\n\ -.catalog-post > * > .fileText:not(:hover) {\n\ - white-space: nowrap;\n\ - overflow: hidden;\n\ - text-overflow: ellipsis;\n\ -}\n\ -.catalog-post > * > .fileText:hover {\n\ - z-index: 1;\n\ -}\n\ -/* overrides 4chan CSS on div.post div.postInfo */\n\ -.catalog-post > .postInfo.postInfo {\n\ - width: auto;\n\ -}\n\ -.catalog-post > * > .subject {\n\ - display: block;\n\ -}\n\ -.catalog-post > * > .dateTime {\n\ - display: inline-block;\n\ - font-style: italic;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover > * > * > .nameBlock,\n\ -:root.catalog-hover-expand .catalog-container:hover > * > * > .dateTime,\n\ -:root.catalog-hover-expand .catalog-container:hover > * > .postMessage:not(:empty) {\n\ - padding-top: .3em;\n\ -}\n\ -.catalog-post .extra-linebreak {\n\ - content: ''; /* makes this work in Blink/WebKit */\n\ - display: block;\n\ - margin-top: .3em;\n\ -}\n\ -.catalog-reply {\n\ - text-align: left;\n\ - white-space: nowrap;\n\ - border-top: 1px solid transparent;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ -}\n\ -.catalog-reply > * {\n\ - padding: 3px;\n\ - overflow: hidden;\n\ - -webkit-flex: none;\n\ - flex: none;\n\ -}\n\ -.catalog-reply > span {\n\ - font-style: italic;\n\ - font-weight: bold;\n\ -}\n\ -.catalog-reply-excerpt {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ -}\n\ -.catalog-post .prettyprinted {\n\ - max-width: 100%;\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ -}\n\ -.catalog-post .MathJax_Display {\n\ - text-align: center !important;\n\ -}\n\ -.catalog-container:not(:hover) .exif,\n\ -:root:not(.catalog-hover-expand) .catalog-container .exif {\n\ - display: none !important;\n\ -}\n\ -.catalog-post > * > .exif {\n\ - border-collapse: collapse;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover .exif[style*=\"display: block;\"] {\n\ - display: inline-block !important;\n\ -}\n\ -.catalog-post > * > .exif,\n\ -.catalog-post > * > .exif > tbody {\n\ - background-color: inherit;\n\ -}\n\ -.catalog-post > * > .exif,\n\ -.catalog-post > * > .exif td {\n\ - min-width: 0;\n\ -}\n\ -.catalog-post > * > .exif td {\n\ - padding-top: 1px;\n\ -}\n\ -:root.hats-enabled .catalog-thread::after {\n\ - content: '';\n\ - pointer-events: none;\n\ - position: absolute;\n\ - background-size: contain;\n\ -}\n\ -:root.hats-enabled .catalog-small > .catalog-thread::after {\n\ - left: -8px;\n\ - top: -59px;\n\ - width: 96px;\n\ - height: 96px;\n\ -}\n\ -:root.hats-enabled:not(.werkTyme) .catalog-small > .catalog-thread:not(.noFile)::after {\n\ - left: calc(67px - .3px * var(--tn-w));\n\ -}\n\ -:root.hats-enabled .catalog-large > .catalog-thread::after {\n\ - left: -15px;\n\ - top: -98px;\n\ - width: 160px;\n\ - height: 160px;\n\ -}\n\ -:root.hats-enabled:not(.werkTyme) .catalog-large > .catalog-thread:not(.noFile)::after {\n\ - left: calc(110px - .5px * var(--tn-w));\n\ -}\n\ -/* Copy Text Link's textarea element */\n\ -textarea.copy-text-element {\n\ - height: 0;\n\ - width: 0;\n\ - position: absolute;\n\ - top: -10000px;\n\ -}\n\ -/* Announcement Hiding */\n\ -:root.hide-announcement $site$psa {\n\ - display: none;\n\ -}\n\ -.hide-announcement-button {\n\ - opacity: 0.4;\n\ - float: left;\n\ -}\n\ -/* Unread */\n\ -.unread-line {\n\ - margin: 0;\n\ - border-color: rgb(255,0,0);\n\ -}\n\ -.unread-line + br {\n\ - display: none;\n\ -}\n\ -.unread-mark-read {\n\ - float: right;\n\ - clear: both;\n\ - width: 100%;\n\ - text-align: right;\n\ -}\n\ -:not(.unread-thread) > .unread-mark-read {\n\ - display: none;\n\ -}\n\ -/* Thread Updater */\n\ -#updater {\n\ - background: none;\n\ - border: none;\n\ - box-shadow: none;\n\ -}\n\ -#updater > .move {\n\ - position: absolute;\n\ - top: -5px;\n\ - bottom: -5px;\n\ - left: -5px;\n\ - right: -5px;\n\ - z-index: -1;\n\ -}\n\ -#updater > div:last-child {\n\ - text-align: center;\n\ -}\n\ -#updater input[type=\"number\"] {\n\ - width: 4em;\n\ -}\n\ -:root.float #updater {\n\ - padding: 0px 3px;\n\ -}\n\ -:root:not(.float).shortcut-icons #updater {\n\ - display: inline-block;\n\ - min-width: 12pt;\n\ - text-align: right;\n\ -}\n\ -.new {\n\ - color: limegreen;\n\ -}\n\ -#update-status:not(.empty) + #update-timer:not(.empty):not(.loading) {\n\ - margin-left: 5px;\n\ -}\n\ -#update-timer {\n\ - cursor: pointer;\n\ -}\n\ -/* Thread Watcher */\n\ -#thread-watcher {\n\ - position: absolute;\n\ -}\n\ -#thread-watcher {\n\ - padding-bottom: 3px;\n\ - padding-left: 3px;\n\ - white-space: nowrap;\n\ - min-width: 146px;\n\ -}\n\ -#watched-threads {\n\ - overflow-x: hidden;\n\ - overflow-y: auto;\n\ -}\n\ -#thread-watcher .refresh {\n\ - padding: 0px 3px;\n\ -}\n\ -:root.fixed-watcher #thread-watcher {\n\ - position: fixed;\n\ -}\n\ -:root.fixed-watcher #watched-threads {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 85vh;\n\ - max-height: calc(100vh - 75px);\n\ -}\n\ -:root:not(.fixed-watcher) #watched-threads:not(:hover) {\n\ - max-height: 210px;\n\ - overflow-y: hidden;\n\ -}\n\ -#thread-watcher > .move {\n\ - padding-top: 3px;\n\ -}\n\ -#watched-threads > div {\n\ - padding-left: 3px;\n\ - padding-right: 3px;\n\ -}\n\ -#watched-threads .watcher-link {\n\ - max-width: 250px;\n\ - display: -webkit-inline-flex;\n\ - display: inline-flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ -}\n\ -#watched-threads .watcher-page,\n\ -#watched-threads .watcher-unread {\n\ - -webkit-flex: 0 0 auto;\n\ - flex: 0 0 auto;\n\ - margin-right: 2px;\n\ -}\n\ -#watched-threads .watcher-title {\n\ - overflow: hidden;\n\ - text-overflow: ellipsis;\n\ - -webkit-flex: 0 1 auto;\n\ - flex: 0 1 auto;\n\ -}\n\ -#watched-threads .watcher-title:not(:first-child) {\n\ - margin-left: 2px;\n\ -}\n\ -.replies-quoting-you > a, #watcher-link.replies-quoting-you, .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -#thread-watcher a {\n\ - text-decoration: none;\n\ -}\n\ -#thread-watcher .move > .close {\n\ - position: absolute;\n\ - right: 0px;\n\ - top: 0px;\n\ - padding: 0px 4px;\n\ -}\n\ -.watch-thread-link {\n\ - padding-top: 18px;\n\ - width: 18px;\n\ - height: 0px;\n\ - display: inline-block;\n\ - background-repeat: no-repeat;\n\ - opacity: 0.2;\n\ - position: relative;\n\ - top: 1px;\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -.watch-thread-link.watched {\n\ - opacity: 1;\n\ -}\n\ -/* Thread Stats */\n\ -#thread-stats {\n\ - background: none;\n\ - border: none;\n\ - box-shadow: none;\n\ -}\n\ -:root.float #thread-stats > .move > :not(#page-count) {\n\ - pointer-events: none;\n\ -}\n\ -:root.float #thread-stats {\n\ - padding: 0px 3px;\n\ -}\n\ -#page-count {\n\ - cursor: pointer;\n\ -}\n\ -/* Quote */\n\ -.hashlink::before {\n\ - content: ' ';\n\ - visibility: hidden;\n\ -}\n\ -.inline + .hashlink {\n\ - display: none !important;\n\ -}\n\ -:root.resurrect-quotes .deadlink {\n\ - text-decoration: none !important;\n\ -}\n\ -.catalog-post .qmark-ct {\n\ - display: none;\n\ -}\n\ -.backlink.deadlink:not(.forwardlink),\n\ -.quotelink.deadlink:not(.forwardlink) {\n\ - text-decoration: underline !important;\n\ -}\n\ -:root:not(.catalog-mode) .inlined {\n\ - opacity: .5;\n\ -}\n\ -#qp input, .forwarded {\n\ - display: none;\n\ -}\n\ -.quotelink.forwardlink,\n\ -.backlink.forwardlink {\n\ - text-decoration: none;\n\ - border-bottom: 1px dashed;\n\ -}\n\ -.filtered {\n\ - text-decoration: underline line-through;\n\ -}\n\ -:root.hide-backlinks .backlink.filtered,\n\ -:root.hide-backlinks .backlink.filtered + .hashlink.filtered {\n\ - display: none;\n\ -}\n\ -.postNum + .container::before {\n\ - content: \" \";\n\ -}\n\ -:root.bottom-backlinks .container {\n\ - display: block;\n\ - clear: both;\n\ - margin: 0 4px;\n\ -}\n\ -:root.bottom-backlinks .backlink {\n\ - font-size: 90%;\n\ -}\n\ -.inline {\n\ - border: 1px solid;\n\ - display: table;\n\ - margin: 2px 0;\n\ -}\n\ -.container ~ .inline {\n\ - margin-left: 20px;\n\ -}\n\ -:root.catalog-mode .inline {\n\ - display: none;\n\ -}\n\ -.inline .post {\n\ - border: 0 !important;\n\ - background-color: transparent !important;\n\ - display: table !important;\n\ - margin: 0 !important;\n\ - padding: 1px 2px !important;\n\ -}\n\ -#qp > .opContainer::after {\n\ - content: '';\n\ - clear: both;\n\ - display: table;\n\ -}\n\ -#qp .post {\n\ - border: none;\n\ - margin: 0;\n\ - padding: 2px 2px 5px;\n\ -}\n\ -#qp img {\n\ - max-height: 80vh;\n\ - max-width: 50vw;\n\ -}\n\ -/* Quote Threading */\n\ -.threadContainer {\n\ - margin-left: 20px;\n\ - border-left: 1px solid rgba(128,128,128,.3);\n\ -}\n\ -.threadOP {\n\ - clear: both;\n\ -}\n\ -/* File */\n\ -.fileText-original,\n\ -.fnswitch:hover > .fntrunc,\n\ -.fnswitch:not(:hover) > .fnfull,\n\ -.expanded-image > .post > .file > .fileThumb > video[data-md5],\n\ -.expanded-image > .post > .file > .fileThumb > img[data-md5] {\n\ - display: none;\n\ -}\n\ -.full-image[data-file-i-d] {\n\ - display: none;\n\ - cursor: pointer;\n\ -}\n\ -.expanded-image > .post > .file > .fileThumb > .full-image {\n\ - display: inline;\n\ -}\n\ -.expanded-image {\n\ - clear: left;\n\ -}\n\ -.expanding {\n\ - opacity: .5;\n\ -}\n\ -:root.fit-height .full-image {\n\ - max-height: 100vh;\n\ -}\n\ -:root.fit-height.fixed .full-image {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 93vh;\n\ - max-height: calc(100vh - 35px);\n\ -}\n\ -:root.fit-width .full-image {\n\ - max-width: 100%;\n\ -}\n\ -:root.ua-gecko.fit-width .full-image {\n\ - width: 100%;\n\ -}\n\ -.fileThumb > .warning {\n\ - clear: both;\n\ -}\n\ -#ihover {\n\ - pointer-events: none;\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 95vh;\n\ - max-height: calc(100vh - 25px);\n\ - max-width: 100vw;\n\ -}\n\ -/* WEBM Metadata */\n\ -.webm-title > a::before {\n\ - content: \"title\";\n\ - text-decoration: underline;\n\ -}\n\ -.webm-title.loading > a::after {\n\ - content: \"...\";\n\ -}\n\ -.webm-title.error > a:hover::before,\n\ -.webm-title.error > a:focus::before {\n\ - content: \"error\";\n\ - text-decoration: none;\n\ -}\n\ -.webm-title > span {\n\ - cursor: text;\n\ -}\n\ -.webm-title.not-found > span::before {\n\ - content: \"not found\";\n\ -}\n\ -.webm-title:not(:hover):not(:focus) > span,\n\ -.webm-title:hover > span + a,\n\ -.webm-title:focus > span + a {\n\ - display: none;\n\ -}\n\ -/* Volume control */\n\ -input[name=\"Default Volume\"] {\n\ - width: 4em;\n\ - height: 1ex;\n\ - vertical-align: middle;\n\ - margin: 0px;\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.fappeTyme $site$replyOriginal.noFile,\n\ -:root.fappeTyme $site$replyOriginal.noFile + br {\n\ - display: none;\n\ -}\n\ -:root.werkTyme $site$thumbLink,\n\ -:root.werkTyme $site$file$thumb,\n\ -:root.werkTyme .catalog-thumb:not(.deleted-file):not(.no-file),\n\ -:root:not(.werkTyme) .werkTyme-filename {\n\ - display: none;\n\ -}\n\ -.werkTyme-filename {\n\ - font-weight: bold;\n\ - font-size: 110%;\n\ -}\n\ -:root.werkTyme .catalog-link {\n\ - box-shadow: 0 0 5px rgba(0, 0, 0, .25);\n\ - padding: 8px;\n\ - text-align: center;\n\ -}\n\ -:root.werkTyme .catalog-thumb {\n\ - box-shadow: none;\n\ - padding: 0;\n\ - vertical-align: middle;\n\ -}\n\ -.indicator {\n\ - background: rgba(255,0,0,0.8);\n\ - font-weight: bold;\n\ - display: inline-block;\n\ - min-width: 9px;\n\ - padding: 0px 2px;\n\ - margin: 0 1px;\n\ - text-align: center;\n\ - color: white;\n\ - border-radius: 2px;\n\ - cursor: pointer;\n\ -}\n\ -:root:not(.fappeTyme) #shortcut-fappe,\n\ -:root:not(.werkTyme) #shortcut-werk {\n\ - display: none;\n\ -}\n\ -/* Index/Reply Navigation */\n\ -#navlinks {\n\ - font-size: 16px;\n\ - top: 25px;\n\ - right: 10px;\n\ -}\n\ -:root.catalog-mode #navlinks {\n\ - display: none;\n\ -}\n\ -/* Highlighting */\n\ -.qphl {\n\ - outline: 2px solid rgba(216, 94, 49, .8);\n\ -}\n\ -:root.highlight-you .quotesYou$site$highlightable$op,\n\ -:root.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8);\n\ -}\n\ -:root.highlight-own .yourPost$site$highlightable$op,\n\ -:root.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8);\n\ -}\n\ -.filter-highlight$site$highlightable$op,\n\ -.filter-highlight$site$highlightable$reply {\n\ - box-shadow: inset 5px 0 rgba(221, 0, 0, .5);\n\ -}\n\ -:root.highlight-own .yourPost > $site$sideArrows,\n\ -:root.highlight-you .quotesYou > $site$sideArrows,\n\ -.filter-highlight > $site$sideArrows {\n\ - color: rgba(221, 0, 0, .8);\n\ -}\n\ -:root.highlight-own .yourPost$site$highlightable$op::after,\n\ -:root.highlight-you .quotesYou$site$highlightable$op::after,\n\ -.filter-highlight$site$highlightable$op::after {\n\ - content: \"\";\n\ - display: block;\n\ - clear: both;\n\ -}\n\ -:root:not(.werkTyme) .catalog-thread.filter-highlight .catalog-thumb,\n\ -:root.werkTyme .catalog-thread.filter-highlight:not(:hover),\n\ -:root.werkTyme:not(.catalog-hover-expand) .catalog-thread.filter-highlight,\n\ -:root.werkTyme.catalog-hover-expand .catalog-thread.filter-highlight > .catalog-container:hover > .catalog-post,\n\ -:root.catalog $site$catalog$thread.filter-highlight$site$highlightable$catalog {\n\ - box-shadow: 0 0 3px 3px rgba(255, 0, 0, .5);\n\ -}\n\ -:root:not(.werkTyme) .catalog-thread.watched .catalog-thumb,\n\ -:root:root.werkTyme .catalog-thread.watched:not(:hover),\n\ -:root:root.werkTyme:not(.catalog-hover-expand) .catalog-thread.watched,\n\ -:root.werkTyme.catalog-hover-expand .catalog-thread.watched > .catalog-container:hover > .catalog-post {\n\ - border: 2px solid rgba(255, 0, 0, .75);\n\ -}\n\ -/* Spoiler text */\n\ -:root.reveal-spoilers $site$spoiler,\n\ -:root.reveal-spoilers $site$spoiler > a {\n\ - color: white !important;\n\ -}\n\ -:root.reveal-spoilers .removed-spoiler::before {\n\ - content: \"[spoiler]\";\n\ -}\n\ -:root.reveal-spoilers .removed-spoiler::after {\n\ - content: \"[/spoiler]\";\n\ -}\n\ -/* Thread & Reply Hiding */\n\ -.hide-thread-button,\n\ -.hide-reply-button {\n\ - float: left;\n\ - margin-right: 4px;\n\ - padding: 2px;\n\ -}\n\ -$site$infoRoot a.hide-reply-button {\n\ - margin-right: 6px;\n\ - padding: 0;\n\ -}\n\ -.replacedSideArrows {\n\ - float: left;\n\ -}\n\ -.hide-thread-button:not(:hover),\n\ -.hide-reply-button:not(:hover) {\n\ - opacity: 0.4;\n\ -}\n\ -.threadContainer .hide-reply-button {\n\ - margin-left: 2px !important;\n\ - position: relative;\n\ - left: 1px;\n\ -}\n\ -.hide-thread-button {\n\ - margin-top: -1px;\n\ - width: 11px;\n\ -}\n\ -.stub ~ :not(.threadDivider) {\n\ - display: none !important;\n\ -}\n\ -.stub input {\n\ - display: inline-block;\n\ -}\n\ -$site$thread[hidden] + hr {\n\ - display: none;\n\ -}\n\ -:root.reply-hide $site$sideArrows {\n\ - display: none;\n\ -}\n\ -:root.sw-yotsuba.thread-hide .party-hat {\n\ - left: 19px;\n\ -}\n\ -/* Anonymize */\n\ -:root.anonymize $site$info$name,\n\ -:root.sw-yotsuba.anonymize .post-author:not([class*=capcode]) {\n\ - font-size: 0;\n\ -}\n\ -:root.anonymize $site$info$tripcode,\n\ -:root.sw-yotsuba.anonymize .n-pu {\n\ - display: none;\n\ -}\n\ -:root.anonymize $site$info$name::before,\n\ -:root.sw-yotsuba.anonymize .post-author:not([class*=capcode])::before {\n\ - content: \"Anonymous\";\n\ - font-size: 10pt;\n\ -}\n\ -:root.sw-yotsuba.anonymize .flashListing .name::before,\n\ -:root.sw-yotsuba.anonymize .post-last > .post-author:not([class*=capcode])::before {\n\ - font-size: 9pt;\n\ -}\n\ -/* QR */\n\ -:root.hide-original-post-form #togglePostFormLink,\n\ -#qr.autohide:not(.focus):not(:hover):not(:active) > form,\n\ -:root.thread-view #qr:not(.show-new-thread-option) select[data-name=\"thread\"],\n\ -#file-n-submit:not(.has-file) #qr-filerm {\n\ - display: none;\n\ -}\n\ -:root.hide-original-post-form #postForm {\n\ - display: none !important;\n\ -}\n\ -#qr select,\n\ -#qr-filename-container > a,\n\ -.remove,\n\ -.captcha-img {\n\ - cursor: pointer;\n\ -}\n\ -#qr {\n\ - position: fixed;\n\ - padding: 1px;\n\ - border: 1px solid transparent;\n\ - min-width: 300px;\n\ - border-radius: 3px 3px 0 0;\n\ -}\n\ -#qr > form {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 85vh;\n\ - max-height: calc(100vh - 75px);\n\ - overflow-y: auto;\n\ - overflow-x: hidden;\n\ -}\n\ -#qrtab {\n\ - border-radius: 3px 3px 0 0;\n\ -}\n\ -#qrtab {\n\ - margin-bottom: 1px;\n\ -}\n\ -#qr .close {\n\ - float: right;\n\ - padding: 0 3px;\n\ -}\n\ -.qr-link-container {\n\ - text-align: center;\n\ - margin: 16px 0;\n\ -}\n\ -.qr-link-container-bottom {\n\ - width: 200px;\n\ - position: absolute;\n\ - left: -100px;\n\ - margin-left: 50%;\n\ - text-align: center;\n\ -}\n\ -.qr-link {\n\ - border-radius: 3px;\n\ - padding: 6px 10px 5px;\n\ - font-weight: bold;\n\ - vertical-align: middle;\n\ - border-style: solid;\n\ - border-width: 1px;\n\ - font-size: 10pt;\n\ -}\n\ -.qr-link-container + #togglePostFormLink {\n\ - font-size: 10pt;\n\ - font-weight: normal;\n\ - margin: -8px 0 3.5px;\n\ -}\n\ -.persona {\n\ - width: 100%;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ -}\n\ -.persona .field {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ - width: 0;\n\ -}\n\ -#qr.forced-anon input[data-name=\"name\"]:not(.force-show),\n\ -#qr.forced-anon input[data-name=\"sub\"]:not(.force-show),\n\ -#qr.reply-to-thread input[data-name=\"sub\"]:not(.force-show),\n\ -body:not(.board_f) #qr select[name=\"filetag\"],\n\ -#qr.reply-to-thread select[name=\"filetag\"],\n\ -#qr:not(.has-sjis) #sjis-toggle,\n\ -#qr:not(.has-math) #tex-preview-button,\n\ -#qr.tex-preview .textarea > :not(#tex-preview),\n\ -#qr:not(.tex-preview) #tex-preview {\n\ - display: none;\n\ -}\n\ -.persona button {\n\ - -webkit-flex: 0 0 23px;\n\ - flex: 0 0 23px;\n\ - -webkit-align-self: stretch;\n\ - align-self: stretch;\n\ - border: 1px solid #BBB;\n\ - padding: 0;\n\ - background: linear-gradient(to bottom, #F8F8F8, #DCDCDC) no-repeat;\n\ - color: #000;\n\ -}\n\ -#qr.sjis-preview #sjis-toggle, #qr.tex-preview #tex-preview-button {\n\ - background: #DCDCDC;\n\ -}\n\ -#sjis-toggle, #qr.sjis-preview textarea.field {\n\ - font-family: \"IPAMonaPGothic\",\"Mona\",\"MS PGothic\",monospace;\n\ - font-size: 16px;\n\ - line-height: 17px;\n\ -}\n\ -#tex-preview-button {\n\ - font-size: 10px;\n\ -}\n\ -#tex-preview {\n\ - white-space: pre-line;\n\ -}\n\ -#qr textarea.field {\n\ - height: 14.8em;\n\ - min-height: 9em;\n\ -}\n\ -#qr.has-captcha textarea.field {\n\ - height: 9em;\n\ -}\n\ -input.field.tripped:not(:hover):not(:focus) {\n\ - color: transparent !important;\n\ - text-shadow: none !important;\n\ -}\n\ -#qr textarea {\n\ - min-width: 300px;\n\ - resize: both;\n\ -}\n\ -.field {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - margin: 0px;\n\ - padding: 2px 4px 3px;\n\ -}\n\ -#qr label input[type=\"checkbox\"] {\n\ - position: relative;\n\ - top: 2px;\n\ -}\n\ -/* Recaptcha v2 */\n\ -#qr .captcha-root {\n\ - position: relative;\n\ -}\n\ -#qr .captcha-container > div {\n\ - margin: auto;\n\ - width: 304px;\n\ -}\n\ -/* XXX scrollable with scroll bar hidden; prevents scroll on space press */\n\ -:root.ua-blink #qr .captcha-container > div,\n\ -:root.ua-edge #qr .captcha-container > div {\n\ - overflow: hidden;\n\ -}\n\ -:root.ua-blink #qr .captcha-container > div > div:first-of-type,\n\ -:root.ua-edge #qr .captcha-container > div > div:first-of-type {\n\ - overflow-y: scroll;\n\ - overflow-x: hidden;\n\ - padding-right: 30px;\n\ - height: 99%;\n\ - width: 100%;\n\ -}\n\ -#qr .captcha-counter {\n\ - display: block;\n\ - width: 100%;\n\ - text-align: center;\n\ - pointer-events: none;\n\ -}\n\ -#qr.captcha-open .captcha-counter {\n\ - position: absolute;\n\ - bottom: 3px;\n\ -}\n\ -#qr .captcha-counter > a {\n\ - pointer-events: auto;\n\ - display: inline-block; /* XXX https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8851747/ */\n\ -}\n\ -#qr:not(.captcha-open) .captcha-counter > a {\n\ - display: block;\n\ - width: 100%;\n\ -}\n\ -#qr.captcha-v2 #qr-captcha-iframe {\n\ - width: 302px;\n\ - height: 423px;\n\ - border: 0;\n\ - display: block;\n\ - margin: auto;\n\ -}\n\ -.goog-bubble-content {\n\ - max-width: 100vw;\n\ - max-height: 100vh;\n\ - overflow: auto;\n\ -}\n\ -.goog-bubble-content iframe {\n\ - position: static !important;\n\ -}\n\ -/* File Input, Submit Button, Oekaki */\n\ -#file-n-submit, #qr .oekaki {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ - height: 25px;\n\ - margin-top: 1px;\n\ -}\n\ -#file-n-submit > input, #qr-draw-button {\n\ - background: linear-gradient(to bottom, #F8F8F8, #DCDCDC) no-repeat;\n\ - border: 1px solid #BBB;\n\ - border-radius: 2px;\n\ - height: 100%;\n\ -}\n\ -#qr-file-button, #qr-draw-button {\n\ - width: 15%;\n\ -}\n\ -#file-n-submit input[type=\"submit\"] {\n\ - width: 25%;\n\ -}\n\ -#qr-filename-container {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - position: relative;\n\ - padding: 1px;\n\ -}\n\ -input#qr-filename {\n\ - border: none !important;\n\ - background: none !important;\n\ - outline: none;\n\ -}\n\ -#qr-filename,\n\ -.has-file #qr-no-file {\n\ - display: none;\n\ -}\n\ -#qr-no-file,\n\ -.has-file #qr-filename {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0px; /* XXX Fixes filename not shrinking to allow space for buttons in Edge */\n\ - display: inline-block;\n\ - padding: 0;\n\ - padding-left: 3px;\n\ - overflow: hidden;\n\ - text-overflow: ellipsis;\n\ - white-space: nowrap;\n\ -}\n\ -#qr-no-file {\n\ - color: #AAA;\n\ -}\n\ -#qr .oekaki.has-file {\n\ - display: none;\n\ -}\n\ -#qr .oekaki > label {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - height: 100%;\n\ -}\n\ -#qr .oekaki > label > span {\n\ - margin: 0 3px;\n\ -}\n\ -#qr .oekaki > label > input {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0;\n\ - height: 100%;\n\ -}\n\ -#qr .oekaki-bg {\n\ - position: relative;\n\ - display: inline-block;\n\ - height: 100%;\n\ - width: 10%;\n\ - margin-left: 3px;\n\ -}\n\ -#qr .oekaki-bg > * {\n\ - position: absolute;\n\ - top: 0;\n\ - left: 0;\n\ - margin: 0;\n\ -}\n\ -#qr .oekaki-bg > :not([name=\"oekaki-bgcolor\"]) {\n\ - z-index: 1;\n\ -}\n\ -#qr [name=\"oekaki-bgcolor\"] {\n\ - height: 100%;\n\ - width: 100%;\n\ - border: none;\n\ - padding: 0;\n\ -}\n\ -#qr [name=\"oekaki-bg\"]:not(:checked) ~ [name=\"oekaki-bgcolor\"] {\n\ - visibility: hidden;\n\ -}\n\ -#qr input[type=\"file\"] {\n\ - visibility: hidden;\n\ - position: absolute;\n\ -}\n\ -/* Spoiler Checkbox, QR Icons */\n\ -#qr-filename-container > label, #qr-filename-container > a {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - margin: 0;\n\ - margin-right: 3px;\n\ -}\n\ -#qr:not(.has-spoiler) #qr-spoiler-label,\n\ -#file-n-submit:not(.has-file) #qr-spoiler-label,\n\ -.has-file #paste-area,\n\ -.has-file #url-button,\n\ -#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n\ - display: none;\n\ -}\n\ -#qr-filename-container > label {\n\ - position: relative;\n\ -}\n\ -#qr-filename-container input[type=\"checkbox\"] {\n\ - margin: 0;\n\ -}\n\ -.checkbox-letter {\n\ - font-size: 13px;\n\ - font-weight: bold;\n\ -}\n\ -#qr-filename-container label:not(:hover) > input[type=\"checkbox\"]:not(:focus):not(:checked),\n\ -#qr-filename-container label:not(:hover) > input[type=\"checkbox\"]:not(:focus):not(:checked) ~ :not(.checkbox-letter),\n\ -#qr-filename-container label:hover > .checkbox-letter,\n\ -input[type=\"checkbox\"]:focus ~ .checkbox-letter,\n\ -input[type=\"checkbox\"]:checked ~ .checkbox-letter {\n\ - /* not displayed but still focusable */\n\ - position: absolute;\n\ - opacity: 0;\n\ - pointer-events: none;\n\ -}\n\ -.checkbox-letter, #paste-area, #url-button, #custom-cooldown-button, #dump-button {\n\ - opacity: 0.6;\n\ -}\n\ -#paste-area {\n\ - font-size: 0;\n\ -}\n\ -#paste-area:focus {\n\ - opacity: 1;\n\ -}\n\ -#custom-cooldown-button.disabled {\n\ - opacity: 0.27;\n\ -}\n\ -/* Thread and Flash Tag Select */\n\ -#qr select {\n\ - background: white;\n\ - border: 1px solid #CCC;\n\ -}\n\ -#qr select[data-name=\"thread\"] {\n\ - float: right;\n\ -}\n\ -#qr > form > select {\n\ - margin-top: 1px;\n\ -}\n\ -/* Dumping UI */\n\ -.dump #dump-list-container {\n\ - display: block;\n\ -}\n\ -#dump-list-container {\n\ - display: none;\n\ - position: relative;\n\ - overflow-y: hidden;\n\ - margin-top: 1px;\n\ -}\n\ -#dump-list {\n\ - overflow-x: auto;\n\ - overflow-y: auto;\n\ - white-space: nowrap;\n\ - width: 248px;\n\ - max-height: 248px;\n\ - min-height: 90px;\n\ - max-width: 100%;\n\ - min-width: 100%;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-wrap: wrap;\n\ - flex-wrap: wrap;\n\ -}\n\ -#dump-list:hover {\n\ - overflow-x: auto;\n\ -}\n\ -.qr-preview {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - counter-increment: thumbnails;\n\ - cursor: move;\n\ - display: inline-block;\n\ - height: 90px;\n\ - width: 90px;\n\ - padding: 2px;\n\ - opacity: .5;\n\ - overflow: hidden;\n\ - position: relative;\n\ - text-shadow: 0 0 2px #000;\n\ - -webkit-transition: opacity .25s ease-in-out, -webkit-transform .25s ease-in-out;\n\ - transition: opacity .25s ease-in-out, transform .25s ease-in-out, -webkit-transform .25s ease-in-out;\n\ - vertical-align: top;\n\ - background-size: cover;\n\ - -webkit-flex: none;\n\ - flex: none;\n\ -}\n\ -.qr-preview:hover,\n\ -.qr-preview:focus {\n\ - opacity: .9;\n\ -}\n\ -.qr-preview::before {\n\ - content: counter(thumbnails);\n\ - color: #fff;\n\ - position: absolute;\n\ - top: 3px;\n\ - right: 3px;\n\ - text-shadow: 0 0 3px #000, 0 0 8px #000;\n\ -}\n\ -.qr-preview#selected {\n\ - opacity: 1;\n\ -}\n\ -.qr-preview.drag {\n\ - box-shadow: 0 0 10px rgba(0,0,0,.5);\n\ - -webkit-transform: scale(.8);\n\ - transform: scale(.8);\n\ -}\n\ -.qr-preview.over {\n\ - border-color: #fff;\n\ - -webkit-transform: scale(1.1);\n\ - transform: scale(1.1);\n\ - opacity: 0.9;\n\ - z-index: 10;\n\ -}\n\ -.qr-preview > span {\n\ - color: #fff;\n\ -}\n\ -.remove {\n\ - background: none;\n\ - color: #e00;\n\ - padding: 1px;\n\ -}\n\ -a:only-of-type > .remove {\n\ - display: none;\n\ -}\n\ -.remove:hover::after {\n\ - content: \" Remove\";\n\ -}\n\ -.qr-preview:not(.has-file) label,\n\ -#qr:not(.has-spoiler) .qr-preview-spoiler {\n\ - display: none;\n\ -}\n\ -.qr-preview > label {\n\ - background: rgba(0,0,0,.5);\n\ - color: #fff;\n\ - right: 0;\n\ - bottom: 0;\n\ - left: 0;\n\ - position: absolute;\n\ - text-align: center;\n\ -}\n\ -.qr-preview > label > input {\n\ - margin: 0;\n\ -}\n\ -#add-post {\n\ - cursor: pointer;\n\ - font-size: 2em;\n\ - position: absolute;\n\ - bottom: 20px;\n\ - right: 10px;\n\ - -webkit-transform: translateY(-50%);\n\ - transform: translateY(-50%);\n\ -}\n\ -.textarea {\n\ - position: relative;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ -}\n\ -#char-count {\n\ - color: #000;\n\ - background: hsla(0, 0%, 100%, .5);\n\ - font-size: 8pt;\n\ - position: absolute;\n\ - bottom: 1px;\n\ - right: 1px;\n\ - pointer-events: none;\n\ -}\n\ -#char-count.warning {\n\ - color: red;\n\ -}\n\ -/* Menu */\n\ -.menu-button:not(.fa-bars) {\n\ - display: inline-block;\n\ - position: relative;\n\ - cursor: pointer;\n\ -}\n\ -#header-bar .menu-button i {\n\ - border-top: 6px solid;\n\ - border-right: 4px solid transparent;\n\ - border-left: 4px solid transparent;\n\ - display: inline-block;\n\ - margin: 2px;\n\ - vertical-align: middle;\n\ -}\n\ -.postInfo > .menu-button,\n\ -#thread-watcher .menu-button {\n\ - width: 18px;\n\ - height: 15px;\n\ - text-align: center;\n\ -}\n\ -#menu {\n\ - position: fixed;\n\ - outline: none;\n\ - font-weight: normal;\n\ -}\n\ -#menu, .submenu {\n\ - border-radius: 3px;\n\ - padding-top: 1px;\n\ - padding-bottom: 3px;\n\ -}\n\ -.entry {\n\ - cursor: pointer;\n\ - display: block;\n\ - outline: none;\n\ - padding: 2px 10px;\n\ - position: relative;\n\ - text-decoration: none;\n\ - white-space: nowrap;\n\ - min-width: 70px;\n\ - text-align: left;\n\ - text-shadow: none;\n\ - font-size: 10pt;\n\ -}\n\ -.left>.entry.has-submenu {\n\ - padding-right: 17px !important;\n\ -}\n\ -.entry input[type=\"checkbox\"],\n\ -.entry input[type=\"radio\"] {\n\ - margin: 0px;\n\ - position: relative;\n\ - top: 2px;\n\ -}\n\ -.entry input[type=\"number\"] {\n\ - width: 4.5em;\n\ -}\n\ -.entry.has-shortcut-text {\n\ - display: flex;\n\ - justify-content: space-between;\n\ - align-items: center;\n\ -}\n\ -.entry .shortcut-text {\n\ - opacity: 0.5;\n\ - font-size: 70%;\n\ - margin-left: 5px;\n\ -}\n\ -.has-submenu::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\ -.left .has-submenu::after {\n\ - border-left: 0;\n\ - border-right: .5em solid;\n\ -}\n\ -.submenu {\n\ - display: none;\n\ - position: absolute;\n\ - left: 100%;\n\ - top: -1px;\n\ - margin-left: 0px;\n\ - margin-top: -2px;\n\ -}\n\ -.focused > .submenu {\n\ - display: block;\n\ -}\n\ -.imp-exp-result {\n\ - position: absolute;\n\ - text-align: center;\n\ - margin: auto;\n\ - right: 0px;\n\ - left: 0px;\n\ - width: 200px;\n\ -}\n\ -/* Custom Board Titles */\n\ -.boardTitle, .boardSubtitle {\n\ - white-space: pre-line;\n\ -}\n\ -.boardTitle[contenteditable=\"true\"],\n\ -.boardSubtitle[contenteditable=\"true\"] {\n\ - cursor: text !important;\n\ -}\n\ -/* Embedding */\n\ -.embedder:not(.embedded) > span {\n\ - display: none;\n\ -}\n\ -#embedding {\n\ - padding: 1px 4px 1px 4px;\n\ - position: fixed;\n\ -}\n\ -#embedding.empty {\n\ - display: none;\n\ -}\n\ -#embedding > div:first-child {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ -}\n\ -#embedding .move {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ -}\n\ -#embedding .jump {\n\ - margin: -1px 4px;\n\ - text-decoration: none;\n\ -}\n\ -/* Gallery */\n\ -#a-gallery {\n\ - position: fixed;\n\ - top: 0;\n\ - bottom: 0;\n\ - left: 0;\n\ - right: 0;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ - background: rgba(0,0,0,0.7);\n\ -}\n\ -.gal-viewport {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - overflow: hidden;\n\ -}\n\ -.gal-thumbnails {\n\ - -webkit-flex: 0 0 150px;\n\ - flex: 0 0 150px;\n\ - overflow-y: auto;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: column;\n\ - flex-direction: column;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ - text-align: center;\n\ - background: rgba(0,0,0,.5);\n\ - border-left: 1px solid #222;\n\ -}\n\ -.gal-hide-thumbnails .gal-thumbnails {\n\ - display: none;\n\ -}\n\ -.gal-thumb img,\n\ -.gal-thumb video {\n\ - max-width: 125px;\n\ - max-height: 125px;\n\ - height: auto;\n\ - width: auto;\n\ -}\n\ -.gal-thumb {\n\ - -webkit-flex: 0 0 auto;\n\ - flex: 0 0 auto;\n\ - padding: 3px;\n\ - line-height: 0;\n\ - transition: background .2s linear;\n\ -}\n\ -.gal-highlight {\n\ - background: rgba(0, 190, 255,.8);\n\ -}\n\ -.gal-prev {\n\ - border-right: 1px solid #222;\n\ -}\n\ -.gal-next {\n\ - border-left: 1px solid #222;\n\ -}\n\ -.gal-prev,\n\ -.gal-next {\n\ - -webkit-flex: 0 0 20px;\n\ - flex: 0 0 20px;\n\ - position: relative;\n\ - cursor: pointer;\n\ - opacity: 0.7;\n\ - background-color: rgba(0, 0, 0, 0.3);\n\ -}\n\ -.gal-prev:hover,\n\ -.gal-next:hover {\n\ - opacity: 1;\n\ -}\n\ -.gal-prev::after,\n\ -.gal-next::after {\n\ - position: absolute;\n\ - top: 48.6%;\n\ - -webkit-transform: translateY(-50%);\n\ - transform: translateY(-50%);\n\ - display: inline-block;\n\ - border-top: 11px solid transparent;\n\ - border-bottom: 11px solid transparent;\n\ - content: \"\";\n\ -}\n\ -.gal-prev::after {\n\ - border-right: 12px solid #fff;\n\ - right: 5px;\n\ -}\n\ -.gal-next::after {\n\ - border-left: 12px solid #fff;\n\ - right: 3px;\n\ -}\n\ -.gal-image {\n\ - -webkit-flex: 1 0 auto;\n\ - flex: 1 0 auto;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: flex-start;\n\ - align-items: flex-start;\n\ - -webkit-justify-content: space-around;\n\ - justify-content: space-around;\n\ - overflow: hidden;\n\ - /* Flex > Non-Flex child max-width and overflow fix (Firefox only?) */\n\ - width: 1%;\n\ -}\n\ -:root:not(.gal-fit-height):not(.gal-pdf) .gal-image {\n\ - overflow-y: scroll !important;\n\ -}\n\ -:root:not(.gal-fit-width):not(.gal-pdf) .gal-image {\n\ - overflow-x: scroll !important;\n\ -}\n\ -.gal-image a {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: flex-start;\n\ - align-items: flex-start;\n\ - margin: auto;\n\ - line-height: 0;\n\ - max-width: 100%;\n\ -}\n\ -:root.gal-pdf .gal-image a {\n\ - width: 100%;\n\ - height: 100%;\n\ -}\n\ -.gal-image img,\n\ -.gal-image video {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ -}\n\ -.gal-fit-width .gal-image img,\n\ -.gal-fit-width .gal-image video {\n\ - max-width: 100%;\n\ -}\n\ -.gal-fit-height .gal-image img,\n\ -.gal-fit-height .gal-image video {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 95vh;\n\ - max-height: calc(100vh - 25px);\n\ -}\n\ -.gal-image iframe {\n\ - width: 100%;\n\ - height: 100%;\n\ -}\n\ -.gal-buttons {\n\ - font-size: 2em;\n\ - margin-right: 3px;\n\ - padding-left: 7px;\n\ - padding-right: 7px;\n\ - top: 5px;\n\ -}\n\ -:root.gal-pdf .gal-buttons {\n\ - top: 40px;\n\ - background: rgba(0,0,0,0.6) !important;\n\ - border-radius: 3px;\n\ -}\n\ -.gal-buttons a {\n\ - color: #ffffff;\n\ - text-shadow: 0px 0px 1px #000000;\n\ -}\n\ -.gal-buttons i {\n\ - display: inline-block;\n\ - margin: 2px;\n\ - position: relative;\n\ -}\n\ -.gal-start i {\n\ - border-left: 10px solid;\n\ - border-top: 6px solid transparent;\n\ - border-bottom: 6px solid transparent;\n\ - bottom: 1px;\n\ -}\n\ -.gal-stop i {\n\ - border: 5px solid;\n\ - bottom: 2px;\n\ -}\n\ -.gal-buttons.gal-playing > .gal-start,\n\ -.gal-buttons:not(.gal-playing) > .gal-stop {\n\ - display: none;\n\ -}\n\ -.gal-buttons .menu-button i {\n\ - border-top: 10px solid;\n\ - border-right: 6px solid transparent;\n\ - border-left: 6px solid transparent;\n\ - bottom: 2px;\n\ - vertical-align: baseline;\n\ -}\n\ -.gal-labels {\n\ - position: fixed;\n\ - bottom: 6px;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: column;\n\ - flex-direction: column;\n\ - -webkit-align-items: flex-end;\n\ - align-items: flex-end;\n\ -}\n\ -:root:not(.show-sauce) .gal-sauce {\n\ - display: none;\n\ -}\n\ -.gal-name,\n\ -.gal-count,\n\ -.gal-sauce {\n\ - background: rgba(0,0,0,0.6) !important;\n\ - border-radius: 3px;\n\ - padding: 1px 5px 2px 5px;\n\ - margin-top: 3px;\n\ - color: #ffffff !important;\n\ - text-decoration: none !important;\n\ -}\n\ -.gal-sauce a {\n\ - color: #ffffff !important;\n\ -}\n\ -.gal-name:hover,\n\ -.gal-buttons a:hover,\n\ -.gal-sauce a:hover {\n\ - color: rgb(95, 95, 101) !important;\n\ -}\n\ -:root.gal-pdf .gal-buttons a:hover {\n\ - color: rgb(204, 204, 204) !important;\n\ -}\n\ -.gal-buttons,\n\ -.gal-labels {\n\ - position: fixed;\n\ - right: 195px;\n\ -}\n\ -.gal-hide-thumbnails .gal-buttons,\n\ -.gal-hide-thumbnails .gal-labels {\n\ - right: 44px;\n\ -}\n\ -:root:not(.gal-fit-width):not(.gal-pdf) .gal-labels {\n\ - bottom: 23px !important;\n\ -}\n\ -:root.gal-fit-height:not(.gal-pdf):not(.gal-hide-thumbnails) .gal-buttons,\n\ -:root.gal-fit-height:not(.gal-pdf):not(.gal-hide-thumbnails) .gal-labels {\n\ - right: 178px !important;\n\ -}\n\ -:root.gal-hide-thumbnails.gal-fit-height:not(.gal-pdf) .gal-buttons,\n\ -:root.gal-hide-thumbnails.gal-fit-height:not(.gal-pdf) .gal-labels {\n\ - right: 28px !important;\n\ -}\n\ -:root.gallery-open.fixed #header-bar:not(.autohide),\n\ -:root.gallery-open.fixed #header-bar:not(.autohide) #shortcuts .fa::before {\n\ - visibility: hidden;\n\ -}\n\ -/* Mod Contact Links */\n\ -.contact-links {\n\ - margin-left: 2px;\n\ -}\n\ -.move-note > a {\n\ - text-decoration: underline;\n\ -}\n\ -.invisible {\n\ - font-size: 0;\n\ -}\n\ -/* PostJumper */\n\ -.postJumper > .prev,\n\ -.postJumper > .next {\n\ - font-size: 120%;\n\ -}\n\ -/* PSA */\n\ -.fcx-announcement {\n\ - text-align: center;\n\ -}\n\ -.fcx-announcement a {\n\ - text-decoration: underline;\n\ -}\n\ -/* General */\n\ -:root.yotsuba .dialog {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.yotsuba .field:focus,\n\ -:root.yotsuba .field.focus {\n\ - border-color: #EA8;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.yotsuba.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8) !important;\n\ -}\n\ -:root.yotsuba.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.yotsuba #header-bar.dialog {\n\ - background-color: rgba(240,224,214,0.98);\n\ -}\n\ -:root.yotsuba:not(.fixed) #header-bar, :root.yotsuba #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.yotsuba #header-bar, :root.yotsuba #notifications {\n\ - color: #B86;\n\ -}\n\ -:root.yotsuba #board-list a, :root.yotsuba #shortcuts a {\n\ - color: #800000;\n\ -}\n\ -/* Settings */\n\ -:root.yotsuba #fourchanx-settings fieldset, :root.yotsuba .section-main div::before {\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.yotsuba .suboption-list > div:last-of-type {\n\ - background-color: #F0E0D6;\n\ -}\n\ -/* Catalog */\n\ -:root.yotsuba.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #F0E0D6;\n\ -}\n\ -:root.yotsuba.werkTyme .catalog-thread:not(:hover),\n\ -:root.yotsuba.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.yotsuba.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.yotsuba.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #D9BFB7;\n\ -}\n\ -/* Quote */\n\ -:root.yotsuba .backlink.deadlink {\n\ - color: #00E !important;\n\ -}\n\ -:root.yotsuba .inline {\n\ - border-color: #D9BFB7;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.yotsuba .indicator {\n\ - color: #F0E0D6;\n\ -}\n\ -/* QR */\n\ -.yotsuba #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.yotsuba .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.yotsuba .qr-link {\n\ - border-color: rgb(225, 209, 199) rgb(225, 209, 199) rgb(210, 194, 184);\n\ - background: linear-gradient(#FFEFE5, #F0E0D6) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.yotsuba .qr-link:hover {\n\ - background: #F0E0D6;\n\ -}\n\ -/* Menu */\n\ -:root.yotsuba #menu {\n\ - color: #800000;\n\ -}\n\ -:root.yotsuba .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.yotsuba .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.yotsuba .unread-mark-read {\n\ - background-color: rgba(240,224,214,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.yotsuba .replies-quoting-you > a, :root.yotsuba #watcher-link.replies-quoting-you, :root.yotsuba .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.yotsuba .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.yotsuba-b .dialog {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.yotsuba-b .field:focus,\n\ -:root.yotsuba-b .field.focus {\n\ - border-color: #98E;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.yotsuba-b.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8) !important;\n\ -}\n\ -:root.yotsuba-b.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.yotsuba-b #header-bar.dialog {\n\ - background-color: rgba(214,218,240,0.98);\n\ -}\n\ -:root.yotsuba-b:not(.fixed) #header-bar, :root.yotsuba-b #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\n\ - color: #89A;\n\ -}\n\ -:root.yotsuba-b #board-list a, :root.yotsuba-b #shortcuts a {\n\ - color: #34345C;\n\ -}\n\ -/* Settings */\n\ -:root.yotsuba-b #fourchanx-settings fieldset, :root.yotsuba-b .section-main div::before {\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.yotsuba-b .suboption-list > div:last-of-type {\n\ - background-color: #D6DAF0;\n\ -}\n\ -/* Catalog */\n\ -:root.yotsuba-b.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #D6DAF0;\n\ -}\n\ -:root.yotsuba-b.werkTyme .catalog-thread:not(:hover),\n\ -:root.yotsuba-b.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.yotsuba-b.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.yotsuba-b.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #B7C5D9;\n\ -}\n\ -/* Quote */\n\ -:root.yotsuba-b .backlink.deadlink {\n\ - color: #34345C !important;\n\ -}\n\ -:root.yotsuba-b .inline {\n\ - border-color: #B7C5D9;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.yotsuba-b .indicator {\n\ - color: #D6DAF0;\n\ -}\n\ -/* QR */\n\ -.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.yotsuba-b .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.yotsuba-b .qr-link {\n\ - border-color: rgb(199, 203, 225) rgb(199, 203, 225) rgb(184, 188, 210);\n\ - background: linear-gradient(#E5E9FF, #D6DAF0) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.yotsuba-b .qr-link:hover {\n\ - background: #D9DDF3;\n\ -}\n\ -/* Menu */\n\ -:root.yotsuba-b #menu {\n\ - color: #000;\n\ -}\n\ -:root.yotsuba-b .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.yotsuba-b .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.yotsuba-b .unread-mark-read {\n\ - background-color: rgba(214,218,240,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.yotsuba-b .replies-quoting-you > a, :root.yotsuba-b #watcher-link.replies-quoting-you {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.yotsuba-b .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.futaba .dialog {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.futaba .field:focus,\n\ -:root.futaba .field.focus {\n\ - border-color: #EA8;\n\ -}\n\ -/* Header */\n\ -:root.futaba #header-bar.dialog {\n\ - background-color: rgba(240,224,214,0.98);\n\ -}\n\ -:root.futaba:not(.fixed) #header-bar, :root.futaba #notifications {\n\ - font-size: 11pt;\n\ -}\n\ -:root.futaba #header-bar, :root.futaba #notifications {\n\ - color: #B86;\n\ -}\n\ -:root.futaba #header-bar a, :root.futaba #notifications a {\n\ - color: #800000;\n\ -}\n\ -/* Settings */\n\ -:root.futaba #fourchanx-settings fieldset, :root.futaba .section-main div::before {\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.futaba .suboption-list > div:last-of-type {\n\ - background-color: #F0E0D6;\n\ -}\n\ -/* Catalog */\n\ -:root.futaba.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #F0E0D6;\n\ -}\n\ -:root.futaba.werkTyme .catalog-thread:not(:hover),\n\ -:root.futaba.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.futaba.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.futaba.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #D9BFB7;\n\ -}\n\ -/* Quote */\n\ -:root.futaba .backlink.deadlink {\n\ - color: #00E !important;\n\ -}\n\ -:root.futaba .inline {\n\ - border-color: #D9BFB7;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.futaba .indicator {\n\ - color: #F0E0D6;\n\ -}\n\ -/* Anonymize */\n\ -:root.futaba.anonymize $site$info$name::before {\n\ - font-size: 12pt;\n\ -}\n\ -/* QR */\n\ -.futaba #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.futaba .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.futaba .qr-link {\n\ - border-color: rgb(225, 209, 199) rgb(225, 209, 199) rgb(210, 194, 184);\n\ - background: linear-gradient(#FFEFE5, #F0E0D6) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.futaba .qr-link:hover {\n\ - background: #F0E0D6;\n\ -}\n\ -/* Menu */\n\ -:root.futaba #menu {\n\ - color: #800000;\n\ -}\n\ -:root.futaba .entry {\n\ - font-size: 12pt;\n\ -}\n\ -:root.futaba .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.futaba .unread-mark-read {\n\ - background-color: rgba(240,224,214,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.futaba .replies-quoting-you > a, :root.futaba #watcher-link.replies-quoting-you, :root.futaba .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.futaba .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.burichan .dialog {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.burichan .field:focus,\n\ -:root.burichan .field.focus {\n\ - border-color: #98E;\n\ -}\n\ -/* Header */\n\ -:root.burichan #header-bar.dialog {\n\ - background-color: rgba(214,218,240,0.98);\n\ -}\n\ -:root.burichan:not(.fixed) #header-bar, :root.burichan #header-bar #notifications {\n\ - font-size: 11pt;\n\ -}\n\ -:root.burichan #header-bar, :root.burichan #header-bar #notifications {\n\ - color: #89A;\n\ -}\n\ -:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\n\ - color: #34345C;\n\ -}\n\ -/* Settings */\n\ -:root.burichan #fourchanx-settings fieldset, :root.burichan .section-main div::before {\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.burichan .suboption-list > div:last-of-type {\n\ - background-color: #D6DAF0;\n\ -}\n\ -/* Catalog */\n\ -:root.burichan.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #D6DAF0;\n\ -}\n\ -:root.burichan.werkTyme .catalog-thread:not(:hover),\n\ -:root.burichan.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.burichan.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.burichan.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #B7C5D9;\n\ -}\n\ -/* Quote */\n\ -:root.burichan .backlink.deadlink {\n\ - color: #34345C !important;\n\ -}\n\ -:root.burichan .inline {\n\ - border-color: #B7C5D9;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.burichan .indicator {\n\ - color: #D6DAF0;\n\ -}\n\ -/* Anonymize */\n\ -:root.burichan.anonymize $site$info$name::before {\n\ - font-size: 12pt;\n\ -}\n\ -/* QR */\n\ -.burichan #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.burichan .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.burichan .qr-link {\n\ - border-color: rgb(199, 203, 225) rgb(199, 203, 225) rgb(184, 188, 210);\n\ - background: linear-gradient(#E5E9FF, #D6DAF0) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.burichan .qr-link:hover {\n\ - background: #D9DDF3;\n\ -}\n\ -/* Menu */\n\ -:root.burichan #menu {\n\ - color: #000000;\n\ -}\n\ -:root.burichan .entry {\n\ - font-size: 12pt;\n\ -}\n\ -:root.burichan .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.burichan .unread-mark-read {\n\ - background-color: rgba(214,218,240,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.burichan .replies-quoting-you > a, :root.burichan #watcher-link.replies-quoting-you, :root.burichan .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.burichan .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.tomorrow .dialog {\n\ - background-color: #282A2E;\n\ - border-color: #111;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.tomorrow #arc-list span.quote {\n\ - color: #B5BD68;\n\ -}\n\ -:root.tomorrow.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8) !important;\n\ -}\n\ -:root.tomorrow.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.tomorrow #header-bar.dialog {\n\ - background-color: rgba(40,42,46,0.9);\n\ -}\n\ -:root.tomorrow:not(.fixed) #header-bar, :root.tomorrow #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.tomorrow #header-bar, :root.tomorrow #notifications {\n\ - color: #C5C8C6;\n\ -}\n\ -:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\n\ - color: #81A2BE;\n\ -}\n\ -:root.tomorrow.shortcut-icons .native-settings {\n\ - background-image: url('//s.4cdn.org/image/favicon-ws.ico');\n\ -}\n\ -/* Settings */\n\ -:root.tomorrow #fourchanx-settings fieldset, :root.tomorrow .section-main div::before {\n\ - border-color: #111;\n\ -}\n\ -:root.tomorrow .suboption-list > div:last-of-type {\n\ - background-color: #282A2E;\n\ -}\n\ -/* Catalog */\n\ -:root.tomorrow.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #282A2E;\n\ -}\n\ -:root.tomorrow.werkTyme .catalog-thread:not(:hover),\n\ -:root.tomorrow.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.tomorrow.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.tomorrow.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #111;\n\ -}\n\ -/* Quote */\n\ -:root.tomorrow .backlink.deadlink {\n\ - color: #81A2BE !important;\n\ -}\n\ -:root.tomorrow .inline {\n\ - border-color: #111;\n\ - background-color: rgba(0, 0, 0, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.tomorrow .indicator {\n\ - color: #282A2E;\n\ -}\n\ -/* Highlighting */\n\ -:root.tomorrow .qphl {\n\ - outline: 2px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.tomorrow.highlight-you .quotesYou$site$highlightable$op,\n\ -:root.tomorrow.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.tomorrow.highlight-own .yourPost$site$highlightable$op,\n\ -:root.tomorrow.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8);\n\ -}\n\ -:root.tomorrow .filter-highlight$site$highlightable$op,\n\ -:root.tomorrow .filter-highlight$site$highlightable$reply {\n\ - box-shadow: inset 5px 0 rgba(145, 182, 214, .5);\n\ -}\n\ -:root.tomorrow.highlight-own .yourPost > $site$sideArrows,\n\ -:root.tomorrow.highlight-you .quotesYou > $site$sideArrows,\n\ -:root.tomorrow .filter-highlight > $site$sideArrows {\n\ - color: rgb(155, 185, 210);\n\ -}\n\ -:root.tomorrow .catalog-thread.filter-highlight .catalog-thumb,\n\ -:root.tomorrow.werkTyme .catalog-thread.filter-highlight:not(:hover),\n\ -:root.tomorrow.werkTyme:not(.catalog-hover-expand) .catalog-thread.filter-highlight,\n\ -:root.tomorrow.werkTyme.catalog-hover-expand .catalog-thread.filter-highlight > .catalog-container:hover > .catalog-post {\n\ - box-shadow: 0 0 3px 3px rgba(64, 192, 255, .7);\n\ -}\n\ -:root.tomorrow .catalog-thread.watched .catalog-thumb,\n\ -:root.tomorrow.werkTyme .catalog-thread.watched:not(:hover),\n\ -:root.tomorrow.werkTyme:not(.catalog-hover-expand) .catalog-thread.watched,\n\ -:root.tomorrow.werkTyme.catalog-hover-expand .catalog-thread.watched > .catalog-container:hover > .catalog-post {\n\ - border: 2px solid rgb(64, 192, 255);\n\ -}\n\ -/* QR */\n\ -.tomorrow #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #282A2E;\n\ - border-color: #111;\n\ -}\n\ -:root.tomorrow .qr-preview {\n\ - background-color: rgba(255, 255, 255, .15);\n\ -}\n\ -:root.tomorrow #qr .field {\n\ - background-color: rgb(26, 27, 29);\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.tomorrow #qr .field:focus,\n\ -:root.tomorrow #qr .field.focus {\n\ - border-color: rgb(129, 162, 190) !important;\n\ - background-color: rgb(30,32,36);\n\ -}\n\ -:root.tomorrow .persona button {\n\ - background: linear-gradient(to bottom, #2E3035, #222427) no-repeat;\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ - outline: none;\n\ -}\n\ -:root.tomorrow .persona button::-moz-focus-inner {\n\ - border: none;\n\ -}\n\ -:root.tomorrow .persona button:focus {\n\ - border-color: rgb(129, 162, 190);\n\ -}\n\ -:root.tomorrow #qr.sjis-preview #sjis-toggle,\n\ -:root.tomorrow #qr.tex-preview #tex-preview-button {\n\ - background: rgb(26, 27, 29);\n\ -}\n\ -:root.tomorrow #qr select,\n\ -:root.tomorrow #file-n-submit > input,\n\ -:root.tomorrow #qr-draw-button {\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.tomorrow #qr-filename {\n\ - color: rgb(197,200,198);\n\ -}\n\ -:root.tomorrow .qr-link {\n\ - border-color: rgb(25, 27, 31) rgb(25, 27, 31) rgb(10, 12, 16);\n\ - background: linear-gradient(#37393D, #282A2E) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.tomorrow .qr-link:hover {\n\ - background: #282A2E;\n\ -}\n\ -/* Menu */\n\ -:root.tomorrow #menu {\n\ - color: #C5C8C6;\n\ -}\n\ -:root.tomorrow .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.tomorrow .focused.entry {\n\ - background: rgba(0, 0, 0, .33);\n\ -}\n\ -/* Unread */\n\ -:root.tomorrow .unread-line {\n\ - border-color: rgb(197, 200, 198);\n\ -}\n\ -:root.tomorrow .unread-mark-read {\n\ - background-color: rgba(40,42,46,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.tomorrow .replies-quoting-you > a, :root.tomorrow #watcher-link.replies-quoting-you, :root.tomorrow .last-page > a > .watcher-page {\n\ - color: #F00 !important;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.tomorrow .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.photon .dialog {\n\ - background-color: #DDD;\n\ - border-color: #CCC;\n\ -}\n\ -:root.photon .field:focus,\n\ -:root.photon .field.focus {\n\ - border-color: #EA8;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.photon #arc-list tr:nth-of-type(odd) span.quote {\n\ - color: #C0E17A;\n\ -}\n\ -:root.photon.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8) !important;\n\ -}\n\ -:root.photon.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.photon #header-bar.dialog {\n\ - background-color: rgba(221,221,221,0.98);\n\ -}\n\ -:root.photon:not(.fixed) #header-bar, :root.photon #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.photon #header-bar, :root.photon #notifications {\n\ - color: #333;\n\ -}\n\ -:root.photon #header-bar a, :root.photon #notifications a {\n\ - color: #FF6600;\n\ -}\n\ -/* Settings */\n\ -:root.photon #fourchanx-settings fieldset, :root.photon .section-main div::before {\n\ - border-color: #CCC;\n\ -}\n\ -:root.photon .suboption-list > div:last-of-type {\n\ - background-color: #DDD;\n\ -}\n\ -/* Catalog */\n\ -:root.photon.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #DDD;\n\ -}\n\ -:root.photon.werkTyme .catalog-thread:not(:hover),\n\ -:root.photon.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.photon.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.photon.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #CCC;\n\ -}\n\ -/* Quote */\n\ -:root.photon .backlink.deadlink {\n\ - color: #F60 !important;\n\ -}\n\ -:root.photon .inline {\n\ - border-color: #CCC;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.photon .indicator {\n\ - color: #DDD;\n\ -}\n\ -/* QR */\n\ -.photon #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #DDD;\n\ - border-color: #CCC;\n\ -}\n\ -:root.photon .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.photon .qr-link {\n\ - border-color: rgb(206, 206, 206) rgb(206, 206, 206) rgb(191, 191, 191);\n\ - background: linear-gradient(#ECECEC, #DDD) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.photon .qr-link:hover {\n\ - background: #DDDDDD;\n\ -}\n\ -/* Menu */\n\ -:root.photon #menu {\n\ - color: #333;\n\ -}\n\ -:root.photon .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.photon .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.photon .unread-mark-read {\n\ - background-color: rgba(221,221,221,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.photon .replies-quoting-you > a, :root.photon #watcher-link.replies-quoting-you, :root.photon .last-page > a > .watcher-page {\n\ - color: #00F !important;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.photon .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.spooky .dialog {\n\ - background-color: #171526;\n\ - border-color: #707070;\n\ -}\n\ -:root.spooky .field:focus,\n\ -:root.spooky .field.focus {\n\ - border-color: #98E;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.spooky #arc-list span.quote {\n\ - color: #634C2C;\n\ -}\n\ -:root.spooky.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8) !important;\n\ -}\n\ -:root.spooky.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.spooky #header-bar.dialog {\n\ - background-color: rgba(23,21,38,0.98);\n\ -}\n\ -:root.spooky:not(.fixed) #header-bar, :root.spooky #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.spooky #header-bar, :root.spooky #notifications {\n\ - color: #C49756;\n\ -}\n\ -:root.spooky #board-list a, :root.spooky #shortcuts a {\n\ - color: #FE9600;\n\ -}\n\ -:root.spooky.shortcut-icons .native-settings {\n\ - background-image: url('//s.4cdn.org/image/favicon-ws.ico');\n\ -}\n\ -/* Settings */\n\ -:root.spooky #fourchanx-settings fieldset, :root.spooky .section-main div::before {\n\ - border-color: #707070;\n\ -}\n\ -:root.spooky .suboption-list > div:last-of-type {\n\ - background-color: #171526;\n\ -}\n\ -/* Catalog */\n\ -:root.spooky.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #171526;\n\ -}\n\ -:root.spooky.werkTyme .catalog-thread:not(:hover),\n\ -:root.spooky.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.spooky.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.spooky.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #707070;\n\ -}\n\ -/* Quote */\n\ -:root.spooky .backlink.deadlink {\n\ - color: #FE9600 !important;\n\ -}\n\ -:root.spooky .inline {\n\ - border-color: #707070;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.spooky .indicator {\n\ - color: #171526;\n\ -}\n\ -/* Highlighting */\n\ -:root.spooky .qphl {\n\ - outline: 2px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.spooky.highlight-you .quotesYou$site$highlightable$op,\n\ -:root.spooky.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.spooky.highlight-own .yourPost$site$highlightable$op,\n\ -:root.spooky.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8);\n\ -}\n\ -:root.spooky .filter-highlight$site$highlightable$op,\n\ -:root.spooky .filter-highlight$site$highlightable$reply {\n\ - box-shadow: inset 5px 0 rgba(145, 182, 214, .5);\n\ -}\n\ -:root.spooky.highlight-own .yourPost > $site$sideArrows,\n\ -:root.spooky.highlight-you .quotesYou > $site$sideArrows,\n\ -:root.spooky .filter-highlight > $site$sideArrows {\n\ - color: rgb(155, 185, 210);\n\ -}\n\ -/* QR */\n\ -.spooky #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #171526;\n\ - border-color: #707070;\n\ -}\n\ -:root.spooky .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.spooky #qr .field {\n\ - background-color: rgb(26, 27, 29);\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.spooky #qr .field:focus,\n\ -:root.spooky #qr .field.focus {\n\ - border-color: rgb(254, 150, 0) !important;\n\ - background-color: rgb(30,32,36);\n\ -}\n\ -:root.spooky .persona button {\n\ - background: linear-gradient(to bottom, #2E3035, #222427) no-repeat;\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ - outline: none;\n\ -}\n\ -:root.spooky .persona button::-moz-focus-inner {\n\ - border: none;\n\ -}\n\ -:root.spooky .persona button:focus {\n\ - border-color: rgb(254, 150, 0);\n\ -}\n\ -:root.spooky #qr.sjis-preview #sjis-toggle,\n\ -:root.spooky #qr.tex-preview #tex-preview-button {\n\ - background: rgb(26, 27, 29);\n\ -}\n\ -:root.spooky #qr select,\n\ -:root.spooky #file-n-submit > input,\n\ -:root.spooky #qr-draw-button {\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.spooky #qr-filename {\n\ - color: rgb(197,200,198);\n\ -}\n\ -:root.spooky .qr-link {\n\ - border-color: rgb(8, 6, 23) rgb(8, 6, 23) rgb(0, 0, 8);\n\ - background: linear-gradient(#262435, #171526) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.spooky .qr-link:hover {\n\ - background: #1A1829;\n\ -}\n\ -/* Menu */\n\ -:root.spooky #menu {\n\ - color: #FE9600;\n\ -}\n\ -:root.spooky .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.spooky .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.spooky .unread-line {\n\ - border-color: rgb(197, 200, 198);\n\ - visibility: visible;\n\ - opacity: 1;\n\ -}\n\ -:root.spooky .unread-mark-read {\n\ - background-color: rgba(23,21,38,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.spooky .replies-quoting-you > a, :root.spooky #watcher-link.replies-quoting-you, :root.spooky .last-page > a > .watcher-page {\n\ - color: #F00 !important;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.spooky .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* Link Title Favicons */\n\ -.linkify.audio::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.bitchute::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAadQTFRFAAAAwzw8xDs7cY6O0iws0ysrtF9f0Sws1CwsyzU1zTIy1igoyzQ01icnY7i4t0hI0S4u0ysr1Soq1ikp1ikp1Soq0ysr0S4uu0VFzjEx1Csr1ygo2Ccn2Ccn1ygo1CoqzjExzjAw1Skp2Ccn2Ccn1ikp0TAwxzY21Soq1SoqyzQ00iws1ygo1ygo0yws1Soq1Skp1igo1igo1igo1igo1igo1igo1Coq1Soq0C0t1ygo1ygo0S4unV5e1Csr1ygo1ygo1CsruUdHxzg41Skp1ygo1CsryTU10C4u1igo1ycn1ygo0i0txjo60S0t1ikp1ygo1ikp1Cws1Coq1Coq0yws0S0tyzQ00iws1Soq0ysr0i0txDs72Ccn2CUl2CYm2CQk3EFB2S8v2zw82jY24FZW3D0931FR3EBA3UND8LS04FVV7qys4V9f4WBg+erq766u9t7e7qqq2Ckp54KC9+Pj6pSU+Ojo5XNz9NHR6YqK8bu765ub5G5u9M3N6ImJ88vL5XV165eX3UVF6pWV3UhI2Soq2jU12Coq2jQ02Cgo2Sws////FaxLuAAAAF10Uk5TAAAAAAAAAAAAAAAAAAAAASJnoLy9oWolAhBz1vr72XgTGKf8/a4cCpuiDVvz9mS6xOvy9vzg6aGsPOToRAFv9fh2Awm07XgIMd765UEDOsfemVhhY00nBommbCkEI8horgAAAL5JREFUKBUFwbFKA0EUQNF7387sMq4EmzRpLSSdIBYKFv6Af2prnSYkRT4gWFgkCBJQ0EIFdcZzBCeqqh4qdk7VW2ChPusw02sAYKU7z7wEAAA2piQKFbrWSHazc1J0XWs5pdxPDykcVX+7Y9UxUsSo+s7PibqPFBRV/C5qi4i/UkrJrc7L47Bt4ZWnUaMCAE9GSrtKBQD2fR+bnAEAeOn7dUTOwApe35bDsPz0zsniQlV98IN0tJ3f6P0XAMA/kxou7OXCdnoAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.clyp::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.dailymotion::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.gfycat::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.gist::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABblBMVEXc3NykpKTW1tbb29ugoKCdnZ0AAAACAgIEDRcKCgoMDAwODg4QIzYRDAoTExMUDwwVAg0WICsaEw8aGhoiCBklGxUmERwwKCQ7LSU7Ozs8LSZFLyNINi1JNyxJNy1KSklMOi5VR1FXV1daQTRkZGRseYZwU0F4eHh7dnR8bWV/YE6IdGiKcGCKkJaNgYeNjY2RdGOScWCUcWCZmZmhoaGkpKSoqKirfmaurq6xsbG1tbW6urq+vr7AbmzBb23CwsLGxsbHx8fHyMjJycnJysrMzMzOiYbPi4fQ0NDRoYbT09PU1NTW1tbY2NjZqIzZ2dnb29vd3d3f39/i4uLktZrk5OTl5eXm5ubn5+fo6Ojq6urs7OzttKLu7u7wuqbw8PDx8fHz8/P4+Pj5+fn7uZj8vpz9ya79ybD/tZf/upr/wZ//w6H/xKH/xaL/xrH/yqj/y7T/zqv/z7D/07D/17n/2Lv/2Lz/3L//38n/4Mk3Q/ZuAAAABnRSTlMSFcbGzc5MNKFvAAAA1klEQVQoz2NgYPZHAswMDEwRSclwkBTBxOARn4gE4j0YXBOiJNUDg7y8Ar1UlOITXBkcY73Z2Li42dg42dn4wmIdGeyjQ7nZoEA4PNqewSZKlw0O9KJsGKwjBdl4ZeWkJGQUhNjEIq0ZrMI5+D0ri7Jz8itCRAXCrRgsQ3mUy+xicrPSbfO0REItGSyCVaVL3ONSU9LcCtQUgy0YzIJ85M1LizMzCsv9xF2CzBhMAwN99TV1DI0MtDWcAgNNGUycA5CAswkDi5kDwrMOZiwMjKzGSICVEQDhZj0UQV7PewAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.image::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.installgentoo::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABcVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3dIYAAAAAAAAAAAAbGh4BBAcCBgoBBgoCBwsCCQ/QzucCCA7MyuXZ1eUBBQmTh8fo5/i9svIAAADh3vQAAAACCA0CCQ8CCQ4DDBQbGCUDChDr6vgAAAAAAAAREBIDCxK6tdfe2fTv7/cDCxIDDBQEDRUHDhgMJjXk4PZdXWdLUFoUNEYOKDgSMUMRLUBneI4eTGj08/QmW3onW3rTzvfOx/giU3IiVHMkWHdEaYJobHv3+PokWHpua6TNy9xZgZ+1quz8/foQKj0XPFInWn0nW38tZ4o6fqg8gq48grA9hrU/i7pAhrNAiLdBjLtEjr1FksNIjr5Il8pImMtKWnNqhL97odKFqti5q/q5rPq60+nCt/vLw/vPx/jV0vHY0/rc1/rg2/vh3fzn4fzu6/vx8vf19Pv19Pz49/v5+Pv8/Pv8/fr9/vv+/frziVtUAAAAT3RSTlMABQYHCAoNDhARGRobL0ZOV1xdXV5fYGBmZnB0eX2MjZSaoaGio6mqqqustLq7zubo6Ojo6evt7u/x8fLy9/f4+Pj5+vr6+vr6+/39/v7+XKgUSwAAAMhJREFUKM9jYGDg4OZmZgABKINT1dBAhBHIYFMxMBIDisjbhoZbCTExsCu5hoeY8DEwcOkEx8fY6MqpucTGB0izglVEplcU5/gmRYWBVQDNMK+s0hN3SvMyBpsBNJxXw0NfwTEjVQZqHQMHj5RfWW5mliSEC7TPzK6yJD/bXZQRzGdXcisqLy309okA2Q4Eis4peQWmstqBCdGW/CABraC45ERBBs3A6Fh/AbAKTwsHa34QZW8NVsGuLqwswQSjQICTmYMFQaEDAAF8JHLfKGswAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.liveleak::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAlNJREFUGBkFwU2LVmUYAODrPu8Z5x1xSpRBXQyFoLsBE+wfiO5atJOgnf9DUPwFgtGinUgEaQsRhHYuMtpEiEWuG5iNjuOcj+c8z911xXcXL/68c3Dw1fzhg0QgEQAAEYGUKXFie9vxlSs/xk/rdavjGEkmkWSih65z4osv9GfOiK6LzEyZ2uGh4dUrmzs72ddlUUhkoiMr4PT167589Mh6c1N0nSRlqrX67dat+PDyZXRT19m5edPnt28rGFHxMcJ6d9fprS1/37tneP3aemPD1uamUydPOru3p5DdGOH0tWsu3LhhxIQJM2qEpRT/Pn3q/du3AhARSmvGTH0lplKMrVkiYpVpQaJlighzhDkzhmEA0fcWoqAfyaFW4zTlgCABxlrNmY4ylUzLsiREprFWc0T2M+ZSjKWY0AEaltZUjJixZJIpuk5pTWlNP2BYFvOyKJkCAKU1tTXHrZlqVWolUxdhxsfVSj9FmJfFMM9GdICGGa01HyMstYpMIFPJVNDPmYZSTOPoOEKHzNRlKpmWWh1j6TpLa2SKTKVWU6Z+Qolwdm/P9QcPZKa2LH69e9eIMs+WCL/cv2/98CGZPrt61am+V9APq1X89eyZ/968obVYaiXT4dGREgG+vnPHeHgYMsH2+fP+efEihtVKv7SWw/6+9/v7KYLMhIywTJPamvOXLomukyRsrNf+ePzYkpl9dJ3SWgSCSCQCfz5/7pMLF2yfO6eLiAQcHRz4/cmT+HR7O+Ob3d0fNt69+7a2BiICQCJbA0EgE5lpvbXl1OXL3/8Pfax4+6SjSukAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.pastebin::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB1FBMVEUAAAAAAAAAAABWYWwAAABbY3BbYm5dZnFdZXJeZnMEBAQHCAhYYGpdZnFdZnBgaHIlJyomKCooKi09QkdESU5eZGtdYmhdYmleY2lrcXdqb3Rqb3Rqb3SSmJ+SlJeWmJutr7GtrrCWm6ChpKhbW1tmZmZvb290dHR3d3d4eHh5eXl6enp8fHx+gIJ/f3+CgoKDg4OEhISFhYWHh4eKioqKjI2Li4uMjIyOjo6Pj4+QkJCRkZGSkpKUlJSVl5mWlpaYmZqZm52ampqbm5ucnJydnZ2enp6fn5+hoaGioqKkpKSkpaalpaWmp6mmp6qnqauoqKioqquoqq2qqqqrrK2srKysra6srrCsrrGurq6vr6+wsLCxsbGysrKztLa0tLS1t7m2tra3t7e4uLi5ubm6urq7u7u8vLy9vb2+vr7AwMDAwsTBwcHExcfFxcXFxsnGxsbHx8fIyMjJycnMzMzNzc3Ozs7O0NLPz8/Q0NDR0dHR09XT09PV1dXV1dbV1tfV19rW1tbX19fX19jY2tzZ2dnZ2tva2tra3N3a3N7c3Nze3t7f39/f4OHg4ODi4uLl5+jm5ubs7Ozs7e3u7u7v7+/v8PDw8PDx8fHy8vLz8/P29vYSoLMZAAAAJHRSTlMABAUGCwsNHCAiLzMzMzZEYGJwgIuOnJycnqmqq9bc3+/w8fkZ0N/uAAAA/klEQVQoU2NgYGDl5YMDdgYGBmZZ3964CYFtIR3e9Q7K/AwMHI55KfaFmcHWMy3K3MwlGRg4wz0zdYpcorRbNbL0LaWAAp3ts2umV8wo6MupTauQBgqUG03VL7W3sfZSb1erAgm02M+yzYrVCXUy6zapAQlUx/dEdyX3J3ZHVUYVywAF8o2rDNN1Go2jzGLMokAC2QbuSc42mXmaOXop9iAtCXrJ5qXWjT59Abl2ESJAAX/tSIMMiyrrqQ3T6uS5gQK6kSqpqkUermGTexQFmYACflqR+hlWZSamzQpCLEDPsSmVVDT1TJw0JUhOAMRnYOARFRMTE5cQF+ZiBPIAII5B3EVG0b4AAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.peertube::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABIFBMVEUhHyAAAABzPBnxaA3CWBEnJSYbGRptbW16enpzc3PTayWhb04hHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyApIh+0UhMfHiBWMhvsZg7zaQ0hHyAhHyAXHCHzaQ3xaA3xaA3xaA3xaA0hHyAhHyDxaA3xaA3xaA3xaA3xaA3xaA0oJickIiMdGxwUEhPxaA3xaA3xaA1sbGxwcHB3d3eFhYXxaA3xaA3xaA1zc3Nzc3Nzc3Nzc3Nzc3PxaA3xaA3xaA1zc3Nzc3NtdHjxaA3xaA1yc3STcFnvaA/yaAxzc3N4c2/FbDFzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3MhHyDxaA1zc3MAAAAfljyVAAAAXHRSTlMAAAAAAAAAAAAAAAAZkjMBHOLXYArj8p0u2VsJ1XaGL/OhKyXc1WEN2gwk2/SjKgEYiS4B/tYFGosqAdleAxzj12ML9Z8s850rJWbYeYMs1F8Koiri1V0MGZY0AYbIBFIAAAABYktHRAH/Ai3eAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4wYXFBUVX81QWQAAAKxJREFUGNNVz9UWgkAQANDBtdbu7lZsxe7ubpH//wxBPKDzNvdMAmi0Oj0QQgAYjCazBX7BStvsDqHoAzTtdLklf+Dx+vwICRAIhsKRaCyOvpAwJ6Up8pXOZHOIAFm+UCzJEQuvMhWrIFBUa/WGkodmq40Ad7q9/kDFwnA05lpYYCbT2ZykFvxQDhhmuVpvcvxaHra7vfp72KflcMSYEOB0vlyx+By+3R9PMSfe+P0enM1454kAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTktMDYtMjRUMDM6MjE6MjEtMDc6MDDse6MAAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE5LTA2LTI0VDAzOjIxOjIxLTA3OjAwnSYbvAAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.soundcloud::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.streamable::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABXFBMVEUPkPoNj/qExv0PkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoNj/oPkPoNj/oNj/qExv0PkPpruvwPkPornfoVk/opnPpnufwPkPqExv0Nj/oPkPoNj/oPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoOj/opnPsVk/oMjvoOkPoTkfo6pPsblfo3ovva7v7////v9/5Sr/whmPry+f5htvze8P7W7P5itvyl1v0imPu84P3o9P50v/zN6P73+/8lmvs8pfs+pfsKjvr9/v9EqfsNj/oom/v8/v9nufxAp/tJq/sQkPrb7v6t2f0IjPoclvr6/f9luPwUkvrp9f7h8f5ruvy/4f4kmftpuvwxoPum1v32+/8jmfpMrPvu9/7z+f9UsPs7pPv8/f/4/P9oufwalfpDqPsMj/ounvtVsPsnm/qzfQQ9AAAALXRSTlMAAAAggMzw0IYkBPb4iAamsgZ+jPwogpDO1vTYlPoulL4KivyUCiqO1PL01i67tUAWAAAAAWJLR0Q4oAel1gAAAAd0SU1FB+MGFxMuDXVcMbIAAADdSURBVBjTY2AAAmYWVjY2dg5OBgZGJiCXi4VbFwx4ePlAAlz8unAgIAgUENJFAsJMDMw8unp6+gaGRsYmpoa6IqIMYrp6ZuYWllbW5hY2toZ64gwSurp29g6OTs4urm7uHrqSDGy6nhZeet5WPr5+/gGBelJAgSCLYL+Q0LBw3YjIKKAAu250TGxcvE1CYlJySqquNAOHrl9aukVGZla2RU6uoZ4MA6esrl9evnWBYWFRMdBaOQYGXmSHyQNdyieA4CsogjzHpyQL4SqrqIJ9y8Cgpq6hqaWtogPyPgDmvSxRxBWM9AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOS0wNi0yNFQwMjo0NjoxMy0wNzowMCKUvXUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMDYtMjRUMDI6NDY6MTMtMDc6MDBTyQXJAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.twitchtv::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.twitter::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.video::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vidlii::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACvlBMVEUCWv8HXf8AWv8AAAD///8AVP+bqP8AWv8AVO4AOqUAGkgAyf8APa0AL4QABAsASdEAVv8AUv8AUv8AVP8AWP8BWv8JXv8RYv8QYv8DW/8DXP8xdv9RiP9Af/8IXf8AKP8KXv8JXf8NYf8aaf8ATP0UZP0AVf8AT/8AT/8AVv8ATedvnPVAf/8AT/sYZvl0o/8PYf8udf8aa/8FXf8AVf8AOrRBe/Nvn/8AUv0aaPkXZ/8ATv8AKYQZYuwIXf8ca/wTZP8ASP8AED0HUNwZaf8xdPwDWv8AAAAAQMRcjvQAU/8AMZssb/Jmmf8AU/8AJXsRW+dSif8AUv8AAAAASdQtdP8ATv8AQ/8AQv8APbtKgfQud/8XZ/8TZP8FXP8AKIIcZO4wdP8AF08KU95tnv4gafhZi/Rnl/ZzofcocP8AAAAAQ8Q4efRwnvVmlvVcjvgrcfsAQsQAOK0APrwAQcUEStMLXPgDWv8AHE8APLEARdIAQ80ASeEAVf8AOJkAAAAAAAAAAAAABBMAJJIAY/9rmP+vxv90n/+buPv29/7C1P+zx/n///2Crv/7+fjs8f++z/f///3l6fX9/f/L2fj9/P5ilv9Nh/3h6f6vyf/D0vT///2lwP/Z5Pf3+P9OiP9klvr9/Puzyf+QsPX//fnW4v/k6vfv8/86ev94pfj///uRtf/y8vby9f9Fgv9EgPzt7/jj7f8mcf+eufj///x1pP/Z4fT///52pf9Uivv09fnV4v8ncf64yvj7+/6vxPX///yyyf9ynvr6+vvG1/8ocv3O2/fz9v53ofX8+/nb5v+YuPz//vy0yv8vdP3e5/fn7v/p7PX09//b5P7///6eu/9Df/zq7vjc5//I1vT//v3+/v////9+q/9Tivnn6fPy8/rW4fzI1/2qwv6YtPT8+fX39/jz9PqJrveTsvqfpuxrAAAAhXRSTlMAAAAAAAAAAAAAAAAAAAAABSlERA45nrSzP3TZ7e12Ao2LusMcrJYhFwaR/uhCwP/x5tZzBWHy+n3OvA8u17jmpwgPrOz5jAF2+3FA7PdYG8fuPQaX5jAGAV/39MCmdy/e/RGz/vj5/f/rAXj4//z13n52i5qmmFQ1lqOQaTgIBAYKEAYAKGjtAgAAAKNJREFUGBkFwT0uRGEYBtD3ZJ77uT8iGrXCAixCr7OCyRA2oCKqiUYkOgoJwhqUbMAKLEChVYhk4pxswvcWfFGVEbYtuJutqir9Ibc0uh0+V+mf5gY69yN2PzKJiTjCg8qa3uLRAJpKM9AMoL1VOi9zJ4CQ9z0jwHX+RAwAURUxAMSB/L7u35wCGlKaHrDkPGVmwhlc6FN6l1iHKxupn+djAPgHrEwa+qrzy0oAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vimeo::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vine::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vocaroo::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.youtube::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -/* XXX Moved to end of stylesheet to avoid breaking whole stylesheet in Maxthon. */\n\ -@supports (text-decoration-style: dashed) or (-moz-text-decoration-style: dashed) {\n\ - .quotelink.forwardlink,\n\ - .backlink.forwardlink {\n\ - text-decoration: underline;\n\ - -moz-text-decoration-style: dashed;\n\ - text-decoration-style: dashed;\n\ - border-bottom: none;\n\ - }\n\ -}\n", - -report: -"#g-recaptcha,\n\ -:root:not(.js-enabled) #captchaContainerAlt {\n\ - height: auto;\n\ -}\n\ -#captchaContainerAlt td:nth-child(2) {\n\ - display: table-cell !important;\n\ -}\n\ -/* Archive reports */\n\ -#archive-report {\n\ - padding: 3px;\n\ -}\n\ -#archive-report-enabled {\n\ - vertical-align: middle;\n\ -}\n\ -#archive-report > label {\n\ - display: block;\n\ -}\n\ -#archive-report-reason {\n\ - display: block;\n\ - width: 98%;\n\ -}\n\ -.archive-report-success {\n\ - color: green;\n\ -}\n\ -.archive-report-error {\n\ - color: red;\n\ -}", - -www: -"#captcha-cnt {\n\ - height: auto;\n\ -}\n\ -:root:not(.js-enabled) #form {\n\ - display: block;\n\ -}\n\ -#bd > div[style], #bd > div[style] > * {\n\ - height: auto !important;\n\ - margin: 0 !important;\n\ - font-size: 0;\n\ -}\n", - -sub: function(css) { - var variables = { - site: g.SITE.selectors - }; - return css.replace(/\$[\w\$]+/g, function(name) { - var words = name.slice(1).split('$'); - var sel = variables; - for (var i = 0; i < words.length; i++) { - if (typeof sel !== 'object') return ':not(*)'; - sel = $.getOwn(sel, words[i]); - } - if (typeof sel !== 'string') return ':not(*)'; - return sel; - }); -} - -}; - -$ = (function() { - var $, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - $ = function(selector, root) { - if (root == null) { - root = d.body; - } - return root.querySelector(selector); - }; - - $.DAY = 24 * ($.HOUR = 60 * ($.MINUTE = 60 * ($.SECOND = 1000))); - - $.id = function(id) { - return d.getElementById(id); - }; - - $.ready = function(fc) { - var cb; - if (d.readyState !== 'loading') { - $.queueTask(fc); - return; - } - cb = function() { - $.off(d, 'DOMContentLoaded', cb); - return fc(); - }; - return $.on(d, 'DOMContentLoaded', cb); - }; - - $.formData = function(form) { - var fd, key, val; - if (form instanceof HTMLFormElement) { - return new FormData(form); - } - fd = new FormData(); - for (key in form) { - val = form[key]; - if (val) { - if (typeof val === 'object' && 'newName' in val) { - fd.append(key, val, val.newName); - } else { - fd.append(key, val); - } - } - } - return fd; - }; - - $.extend = function(object, properties) { - var key, val; - for (key in properties) { - val = properties[key]; - object[key] = val; - } - }; - - $.dict = function() { - return Object.create(null); - }; - - $.dict.clone = function(obj) { - var arr, i, j, key, map, ref, val; - if (typeof obj !== 'object' || obj === null) { - return obj; - } else if (obj instanceof Array) { - arr = []; - for (i = j = 0, ref = obj.length; j < ref; i = j += 1) { - arr.push($.dict.clone(obj[i])); - } - return arr; - } else { - map = Object.create(null); - for (key in obj) { - val = obj[key]; - map[key] = $.dict.clone(val); - } - return map; - } - }; - - $.dict.json = function(str) { - return $.dict.clone(JSON.parse(str)); - }; - - $.hasOwn = function(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - }; - - $.getOwn = function(obj, key) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - return obj[key]; - } else { - return void 0; - } - }; - - $.ajax = (function() { - var pageXHR; - if (window.wrappedJSObject && !XMLHttpRequest.wrappedJSObject) { - pageXHR = XPCNativeWrapper(window.wrappedJSObject.XMLHttpRequest); - } else { - pageXHR = XMLHttpRequest; - } - return function(url, options) { - var err, form, headers, key, onloadend, onprogress, r, ref, responseType, timeout, type, value, withCredentials; - if (options == null) { - options = {}; - } - if (options.responseType == null) { - options.responseType = 'json'; - } - options.type || (options.type = options.form && 'post' || 'get'); - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?(?:4chan|4channel|4cdn)\.org)\/adv\//, '$1//adv/'); - onloadend = options.onloadend, timeout = options.timeout, responseType = options.responseType, withCredentials = options.withCredentials, type = options.type, onprogress = options.onprogress, form = options.form, headers = options.headers; - r = new pageXHR(); - try { - r.open(type, url, true); - ref = headers || {}; - for (key in ref) { - value = ref[key]; - r.setRequestHeader(key, value); - } - $.extend(r, { - onloadend: onloadend, - timeout: timeout, - responseType: responseType, - withCredentials: withCredentials - }); - $.extend(r.upload, { - onprogress: onprogress - }); - $.on(r, 'error', function() { - if (!r.status) { - return c.warn("4chan X failed to load: " + url); - } - }); - r.send(form); - } catch (error) { - err = error; - if (err.result !== 0x805e0006) { - throw err; - } - r.onloadend = onloadend; - $.queueTask($.event, 'error', null, r); - $.queueTask($.event, 'loadend', null, r); - } - return r; - }; - })(); - - $.lastModified = $.dict(); - - $.whenModified = function(url, bucket, cb, options) { - var ajax, headers, params, r, ref, t, timeout, url0; - if (options == null) { - options = {}; - } - timeout = options.timeout, ajax = options.ajax; - params = []; - if ($.engine === 'blink') { - params.push("s=" + bucket); - } - if (url.split('/')[2] === 'a.4cdn.org') { - params.push("t=" + (Date.now())); - } - url0 = url; - if (params.length) { - url += '?' + params.join('&'); - } - headers = $.dict(); - if ((t = (ref = $.lastModified[bucket]) != null ? ref[url0] : void 0) != null) { - headers['If-Modified-Since'] = t; - } - r = (ajax || $.ajax)(url, { - onloadend: function() { - var base; - ((base = $.lastModified)[bucket] || (base[bucket] = $.dict()))[url0] = this.getResponseHeader('Last-Modified'); - return cb.call(this); - }, - timeout: timeout, - headers: headers - }); - return r; - }; - - (function() { - var reqs; - reqs = $.dict(); - $.cache = function(url, cb, options) { - var ajax, onloadend, req; - if (options == null) { - options = {}; - } - ajax = options.ajax; - if ((req = reqs[url])) { - if (req.callbacks) { - req.callbacks.push(cb); - } else { - $.queueTask(function() { - return cb.call(req, { - isCached: true - }); - }); - } - return req; - } - onloadend = function() { - var fn1, j, len, ref; - if (!this.status) { - delete reqs[url]; - } - ref = this.callbacks; - fn1 = (function(_this) { - return function(cb) { - return $.queueTask(function() { - return cb.call(_this, { - isCached: false - }); - }); - }; - })(this); - for (j = 0, len = ref.length; j < len; j++) { - cb = ref[j]; - fn1(cb); - } - return delete this.callbacks; - }; - req = (ajax || $.ajax)(url, { - onloadend: onloadend - }); - req.callbacks = [cb]; - return reqs[url] = req; - }; - return $.cleanCache = function(testf) { - var url; - for (url in reqs) { - if (testf(url)) { - delete reqs[url]; - } - } - }; - })(); - - $.cb = { - checked: function() { - if ($.hasOwn(Conf, this.name)) { - $.set(this.name, this.checked); - return Conf[this.name] = this.checked; - } - }, - value: function() { - if ($.hasOwn(Conf, this.name)) { - $.set(this.name, this.value.trim()); - return Conf[this.name] = this.value; - } - } - }; - - $.asap = function(test, cb) { - if (test()) { - return cb(); - } else { - return setTimeout($.asap, 25, test, cb); - } - }; - - $.onExists = function(root, selector, cb) { - var el, observer; - if (el = $(selector, root)) { - return cb(el); - } - observer = new MutationObserver(function() { - if (el = $(selector, root)) { - observer.disconnect(); - return cb(el); - } - }); - return observer.observe(root, { - childList: true, - subtree: true - }); - }; - - $.addStyle = function(css, id, test) { - var style; - if (test == null) { - test = 'head'; - } - style = $.el('style', { - textContent: css - }); - if (id != null) { - style.id = id; - } - $.onExists(doc, test, function() { - return $.add(d.head, style); - }); - return style; - }; - - $.addCSP = function(policy) { - var head, meta; - meta = $.el('meta', { - httpEquiv: 'Content-Security-Policy', - content: policy - }); - if (d.head) { - $.add(d.head, meta); - return $.rm(meta); - } else { - head = $.add(doc || d, $.el('head')); - $.add(head, meta); - return $.rm(head); - } - }; - - $.x = function(path, root) { - root || (root = d.body); - return d.evaluate(path, root, null, 8, null).singleNodeValue; - }; - - $.X = function(path, root) { - root || (root = d.body); - return d.evaluate(path, root, null, 7, null); - }; - - $.addClass = function() { - var className, classNames, el, j, len; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (j = 0, len = classNames.length; j < len; j++) { - className = classNames[j]; - el.classList.add(className); - } - }; - - $.rmClass = function() { - var className, classNames, el, j, len; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (j = 0, len = classNames.length; j < len; j++) { - className = classNames[j]; - el.classList.remove(className); - } - }; - - $.toggleClass = function(el, className) { - return el.classList.toggle(className); - }; - - $.hasClass = function(el, className) { - return indexOf.call(el.classList, className) >= 0; - }; - - $.rm = function(el) { - return el != null ? el.remove() : void 0; - }; - - $.rmAll = function(root) { - return root.textContent = null; - }; - - $.tn = function(s) { - return d.createTextNode(s); - }; - - $.frag = function() { - return d.createDocumentFragment(); - }; - - $.nodes = function(nodes) { - var frag, j, len, node; - if (!(nodes instanceof Array)) { - return nodes; - } - frag = $.frag(); - for (j = 0, len = nodes.length; j < len; j++) { - node = nodes[j]; - frag.appendChild(node); - } - return frag; - }; - - $.add = function(parent, el) { - return parent.appendChild($.nodes(el)); - }; - - $.prepend = function(parent, el) { - return parent.insertBefore($.nodes(el), 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, properties2) { - var el; - el = d.createElement(tag); - if (properties) { - $.extend(el, properties); - } - if (properties2) { - $.extend(el, properties2); - } - return el; - }; - - $.on = function(el, events, handler) { - var event, j, len, ref; - ref = events.split(' '); - for (j = 0, len = ref.length; j < len; j++) { - event = ref[j]; - el.addEventListener(event, handler, false); - } - }; - - $.off = function(el, events, handler) { - var event, j, len, ref; - ref = events.split(' '); - for (j = 0, len = ref.length; j < len; j++) { - event = ref[j]; - el.removeEventListener(event, handler, false); - } - }; - - $.one = function(el, events, handler) { - var cb; - cb = function(e) { - $.off(el, events, cb); - return handler.call(this, e); - }; - return $.on(el, events, cb); - }; - - $.event = function(event, detail, root) { - if (root == null) { - root = d; - } - if ((detail != null) && typeof cloneInto === 'function') { - detail = cloneInto(detail, d.defaultView); - } - return root.dispatchEvent(new CustomEvent(event, { - bubbles: true, - cancelable: true, - detail: detail - })); - }; - - (function() { - var clone, err, ref, unsafeConstructors; - if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { - return; - } - try { - return new CustomEvent('x', { - detail: {} - }); - } catch (error) { - err = error; - unsafeConstructors = { - Object: unsafeWindow.Object, - Array: unsafeWindow.Array - }; - clone = function(obj) { - var constructor, key, obj2, val; - if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { - obj2 = new constructor(); - for (key in obj) { - val = obj[key]; - obj2[key] = clone(val); - } - return obj2; - } else { - return obj; - } - }; - return $.event = function(event, detail, root) { - if (root == null) { - root = d; - } - return root.dispatchEvent(new CustomEvent(event, { - bubbles: true, - cancelable: true, - detail: clone(detail) - })); - }; - } - })(); - - $.modifiedClick = function(e) { - return e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0; - }; - - $.open = (typeof GM !== "undefined" && GM !== null ? GM.openInTab : void 0) != null ? GM.openInTab : typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { - return window.open(url, '_blank'); - }; - - $.debounce = function(wait, fn) { - var args, exec, lastCall, that, timeout; - lastCall = 0; - timeout = null; - that = null; - args = null; - exec = function() { - lastCall = Date.now(); - return fn.apply(that, args); - }; - return function() { - args = arguments; - that = this; - if (lastCall < Date.now() - wait) { - return exec(); - } - clearTimeout(timeout); - return timeout = setTimeout(exec, wait); - }; - }; - - $.queueTask = (function() { - var execTask, taskChannel, taskQueue; - taskQueue = []; - execTask = function() { - var args, func, task; - task = taskQueue.shift(); - func = task[0]; - args = Array.prototype.slice.call(task, 1); - return func.apply(func, args); - }; - if (window.MessageChannel) { - taskChannel = new MessageChannel(); - taskChannel.port1.onmessage = execTask; - return function() { - taskQueue.push(arguments); - return taskChannel.port2.postMessage(null); - }; - } else { - return function() { - taskQueue.push(arguments); - return setTimeout(execTask, 0); - }; - } - })(); - - $.global = function(fn, data) { - var script; - if (doc) { - script = $.el('script', { - textContent: "(" + fn + ").call(document.currentScript.dataset);" - }); - if (data) { - $.extend(script.dataset, data); - } - $.add(d.head || doc, script); - $.rm(script); - return script.dataset; - } else { - try { - fn.call(data); - } catch (error) {} - return data; - } - }; - - $.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]; - }; - - $.minmax = function(value, min, max) { - return (value < min ? min : value > max ? max : value); - }; - - $.hasAudio = function(video) { - return video.mozHasAudio || !!video.webkitAudioDecodedByteCount; - }; - - $.luma = function(rgb) { - return rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114; - }; - - $.unescape = function(text) { - if (text == null) { - return text; - } - return text.replace(/<[^>]*>/g, '').replace(/&(amp|#039|quot|lt|gt|#44);/g, function(c) { - return { - '&': '&', - ''': "'", - '"': '"', - '<': '<', - '>': '>', - ',': ',' - }[c]; - }); - }; - - $.isImage = function(url) { - return /\.(jpe?g|jfif|png|gif|bmp|webp|avif|jxl)$/i.test(url); - }; - - $.isVideo = function(url) { - return /\.(webm|mp4|ogv)$/i.test(url); - }; - - $.engine = (function() { - if (/Edge\//.test(navigator.userAgent)) { - return 'edge'; - } - if (/Chrome\//.test(navigator.userAgent)) { - return 'blink'; - } - if (/WebKit\//.test(navigator.userAgent)) { - return 'webkit'; - } - if (/Gecko\/|Goanna/.test(navigator.userAgent)) { - return 'gecko'; - } - })(); - - $.platform = 'userscript'; - - $.hasStorage = (function() { - try { - if (localStorage.getItem(g.NAMESPACE + 'hasStorage') === 'true') { - return true; - } - localStorage.setItem(g.NAMESPACE + 'hasStorage', 'true'); - return localStorage.getItem(g.NAMESPACE + 'hasStorage') === 'true'; - } catch (error) { - return false; - } - })(); - - $.item = function(key, val) { - var item; - item = $.dict(); - item[key] = val; - return item; - }; - - $.oneItemSugar = function(fn) { - return function(key, val, cb) { - if (typeof key === 'string') { - return fn($.item(key, val), cb); - } else { - return fn(key, val); - } - }; - }; - - $.syncing = $.dict(); - - $.securityCheck = function(data) { - if (location.protocol !== 'https:') { - return delete data['Redirect to HTTPS']; - } - }; - - if (((typeof GM !== "undefined" && GM !== null ? GM.deleteValue : void 0) != null) && window.BroadcastChannel && (typeof GM_addValueChangeListener === "undefined" || GM_addValueChangeListener === null)) { - $.syncChannel = new BroadcastChannel(g.NAMESPACE + 'sync'); - $.on($.syncChannel, 'message', function(e) { - var cb, key, ref, results, val; - ref = e.data; - results = []; - for (key in ref) { - val = ref[key]; - if ((cb = $.syncing[key])) { - results.push(cb($.dict.json(JSON.stringify(val)), key)); - } - } - return results; - }); - $.sync = function(key, cb) { - return $.syncing[key] = cb; - }; - $.forceSync = function() {}; - $["delete"] = function(keys, cb) { - var key; - if (!(keys instanceof Array)) { - keys = [keys]; - } - return Promise.all((function() { - var j, len, results; - results = []; - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - results.push(GM.deleteValue(g.NAMESPACE + key)); - } - return results; - })()).then(function() { - var items, j, key, len; - items = $.dict(); - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - items[key] = void 0; - } - $.syncChannel.postMessage(items); - return typeof cb === "function" ? cb() : void 0; - }); - }; - $.get = $.oneItemSugar(function(items, cb) { - var key, keys; - keys = Object.keys(items); - return Promise.all((function() { - var j, len, results; - results = []; - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - results.push(GM.getValue(g.NAMESPACE + key)); - } - return results; - })()).then(function(values) { - var i, j, len, val; - for (i = j = 0, len = values.length; j < len; i = ++j) { - val = values[i]; - if (val) { - items[keys[i]] = $.dict.json(val); - } - } - return cb(items); - }); - }); - $.set = $.oneItemSugar(function(items, cb) { - var key, val; - $.securityCheck(items); - return Promise.all((function() { - var results; - results = []; - for (key in items) { - val = items[key]; - results.push(GM.setValue(g.NAMESPACE + key, JSON.stringify(val))); - } - return results; - })()).then(function() { - $.syncChannel.postMessage(items); - return typeof cb === "function" ? cb() : void 0; - }); - }); - $.clear = function(cb) { - return GM.listValues().then(function(keys) { - return $["delete"](keys.map(function(key) { - return key.replace(g.NAMESPACE, ''); - }), cb); - })["catch"](function() { - return $["delete"](Object.keys(Conf).concat(['previousversion', 'QR Size', 'QR.persona']), cb); - }); - }; - } else { - if (typeof GM_deleteValue === "undefined" || GM_deleteValue === null) { - $.perProtocolSettings = true; - } - if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.getValue = GM_getValue; - $.listValues = function() { - return GM_listValues(); - }; - } else if ($.hasStorage) { - $.getValue = function(key) { - return localStorage.getItem(key); - }; - $.listValues = function() { - var key, results; - results = []; - for (key in localStorage) { - if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { - results.push(key); - } - } - return results; - }; - } else { - $.getValue = function() {}; - $.listValues = function() { - return []; - }; - } - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.setValue = GM_setValue; - $.deleteValue = GM_deleteValue; - } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.oldValue = $.dict(); - $.setValue = function(key, val) { - GM_setValue(key, val); - if (key in $.syncing) { - $.oldValue[key] = val; - if ($.hasStorage) { - return localStorage.setItem(key, val); - } - } - }; - $.deleteValue = function(key) { - GM_deleteValue(key); - if (key in $.syncing) { - delete $.oldValue[key]; - if ($.hasStorage) { - return localStorage.removeItem(key); - } - } - }; - if (!$.hasStorage) { - $.cantSync = true; - } - } else if ($.hasStorage) { - $.oldValue = $.dict(); - $.setValue = function(key, val) { - if (key in $.syncing) { - $.oldValue[key] = val; - } - return localStorage.setItem(key, val); - }; - $.deleteValue = function(key) { - if (key in $.syncing) { - delete $.oldValue[key]; - } - return localStorage.removeItem(key); - }; - } else { - $.setValue = function() {}; - $.deleteValue = function() {}; - $.cantSync = $.cantSet = true; - } - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.sync = function(key, cb) { - return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { - if (remote) { - if (newValue !== void 0) { - newValue = $.dict.json(newValue); - } - return cb(newValue, key); - } - }); - }; - $.forceSync = function() {}; - } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { - $.sync = function(key, cb) { - key = g.NAMESPACE + key; - $.syncing[key] = cb; - return $.oldValue[key] = $.getValue(key); - }; - (function() { - var onChange; - onChange = function(arg) { - var cb, key, newValue; - key = arg.key, newValue = arg.newValue; - if (!(cb = $.syncing[key])) { - return; - } - if (newValue != null) { - if (newValue === $.oldValue[key]) { - return; - } - $.oldValue[key] = newValue; - return cb($.dict.json(newValue), key.slice(g.NAMESPACE.length)); - } else { - if ($.oldValue[key] == null) { - return; - } - delete $.oldValue[key]; - return cb(void 0, key.slice(g.NAMESPACE.length)); - } - }; - $.on(window, 'storage', onChange); - return $.forceSync = function(key) { - key = g.NAMESPACE + key; - return onChange({ - key: key, - newValue: $.getValue(key) - }); - }; - })(); - } else { - $.sync = function() {}; - $.forceSync = function() {}; - } - $["delete"] = function(keys) { - var j, key, len; - if (!(keys instanceof Array)) { - keys = [keys]; - } - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - $.deleteValue(g.NAMESPACE + key); - } - }; - $.get = $.oneItemSugar(function(items, cb) { - return $.queueTask($.getSync, items, cb); - }); - $.getSync = function(items, cb) { - var err, key, val2; - for (key in items) { - if ((val2 = $.getValue(g.NAMESPACE + key))) { - try { - items[key] = $.dict.json(val2); - } catch (error) { - err = error; - if (!/^(?:undefined)*$/.test(val2)) { - throw err; - } - } - } - } - return cb(items); - }; - $.set = $.oneItemSugar(function(items, cb) { - $.securityCheck(items); - return $.queueTask(function() { - var key, value; - for (key in items) { - value = items[key]; - $.setValue(g.NAMESPACE + key, JSON.stringify(value)); - } - return typeof cb === "function" ? cb() : void 0; - }); - }); - $.clear = function(cb) { - $["delete"](Object.keys(Conf)); - $["delete"](['previousversion', 'QR Size', 'QR.persona']); - try { - $["delete"]($.listValues().map(function(key) { - return key.replace(g.NAMESPACE, ''); - })); - } catch (error) {} - return typeof cb === "function" ? cb() : void 0; - }; - } - - return $; - -}).call(this); - -$$ = (function() { - var $$, - slice = [].slice; - - $$ = function(selector, root) { - if (root == null) { - root = d.body; - } - return slice.call(root.querySelectorAll(selector)); - }; - - return $$; - -}).call(this); - -CrossOrigin = (function() { - var CrossOrigin, Request; - - CrossOrigin = { - binary: function(url, cb, headers) { - var fallback, gmOptions; - if (headers == null) { - headers = $.dict(); - } - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?(?:4chan|4channel|4cdn)\.org)\/adv\//, '$1//adv/'); - fallback = function() { - return $.ajax(url, { - headers: headers, - responseType: 'arraybuffer', - onloadend: function() { - if (this.status && this.response) { - return cb(new Uint8Array(this.response), this.getAllResponseHeaders()); - } else { - return cb(null); - } - } - }); - }; - if (!(((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) != null) || (typeof GM_xmlhttpRequest !== "undefined" && GM_xmlhttpRequest !== null))) { - fallback(); - return; - } - gmOptions = { - method: "GET", - url: url, - headers: headers, - responseType: 'arraybuffer', - overrideMimeType: 'text/plain; charset=x-user-defined', - onload: function(xhr) { - var data, i, r; - if (xhr.response instanceof ArrayBuffer) { - data = new Uint8Array(xhr.response); - } else { - r = xhr.responseText; - data = new Uint8Array(r.length); - i = 0; - while (i < r.length) { - data[i] = r.charCodeAt(i); - i++; - } - } - return cb(data, xhr.responseHeaders); - }, - onerror: function() { - return cb(null); - }, - onabort: function() { - return cb(null); - } - }; - try { - return ((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) || GM_xmlhttpRequest)(gmOptions); - } catch (error) { - return fallback(); - } - }, - file: function(url, cb) { - return CrossOrigin.binary(url, function(data, headers) { - var blob, contentDisposition, contentType, match, mime, name, ref, ref1, ref2, ref3, ref4; - if (data == null) { - return cb(null); - } - name = (ref = url.match(/([^\/?#]+)\/*(?:$|[?#])/)) != null ? ref[1] : void 0; - contentType = (ref1 = headers.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; - contentDisposition = (ref2 = headers.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; - mime = (contentType != null ? contentType.match(/[^;]*/)[0] : void 0) || 'application/octet-stream'; - match = (contentDisposition != null ? (ref3 = contentDisposition.match(/\bfilename\s*=\s*"((\\"|[^"])+)"/i)) != null ? ref3[1] : void 0 : void 0) || (contentType != null ? (ref4 = contentType.match(/\bname\s*=\s*"((\\"|[^"])+)"/i)) != null ? ref4[1] : void 0 : void 0); - if (match) { - name = match.replace(/\\"/g, '"'); - } - if (/^text\/plain;\s*charset=x-user-defined$/i.test(mime)) { - mime = $.getOwn(QR.typeFromExtension, name.match(/[^.]*$/)[0].toLowerCase()) || 'application/octet-stream'; - } - blob = new Blob([data], { - type: mime - }); - blob.name = name; - return cb(blob); - }); - }, - Request: Request = (function() { - function Request() {} - - Request.prototype.status = 0; - - Request.prototype.statusText = ''; - - Request.prototype.response = null; - - Request.prototype.responseHeaderString = null; - - Request.prototype.getResponseHeader = function(headerName) { - var header, i, j, key, len, ref, ref1, ref2, val; - if ((this.responseHeaders == null) && (this.responseHeaderString != null)) { - this.responseHeaders = $.dict(); - ref = this.responseHeaderString.split('\r\n'); - for (j = 0, len = ref.length; j < len; j++) { - header = ref[j]; - if ((i = header.indexOf(':')) >= 0) { - key = header.slice(0, i).trim().toLowerCase(); - val = header.slice(i + 1).trim(); - this.responseHeaders[key] = val; - } - } - } - return (ref1 = (ref2 = this.responseHeaders) != null ? ref2[headerName.toLowerCase()] : void 0) != null ? ref1 : null; - }; - - Request.prototype.abort = function() {}; - - Request.prototype.onloadend = function() {}; - - return Request; - - })(), - ajax: function(url, options) { - var gmOptions, gmReq, headers, onloadend, req, responseType, timeout; - if (options == null) { - options = {}; - } - onloadend = options.onloadend, timeout = options.timeout, responseType = options.responseType, headers = options.headers; - if (responseType == null) { - responseType = 'json'; - } - if (!(((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) != null) || (typeof GM_xmlhttpRequest !== "undefined" && GM_xmlhttpRequest !== null))) { - return $.ajax(url, options); - } - req = new CrossOrigin.Request(); - req.onloadend = onloadend; - gmOptions = { - method: 'GET', - url: url, - headers: headers, - timeout: timeout, - onload: function(xhr) { - var response; - try { - response = (function() { - switch (responseType) { - case 'json': - if (xhr.responseText) { - return JSON.parse(xhr.responseText); - } else { - return null; - } - break; - default: - return xhr.responseText; - } - })(); - $.extend(req, { - response: response, - status: xhr.status, - statusText: xhr.statusText, - responseHeaderString: xhr.responseHeaders - }); - } catch (error) {} - return req.onloadend(); - }, - onerror: function() { - return req.onloadend(); - }, - onabort: function() { - return req.onloadend(); - }, - ontimeout: function() { - return req.onloadend(); - } - }; - try { - gmReq = ((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) || GM_xmlhttpRequest)(gmOptions); - } catch (error) { - return $.ajax(url, options); - } - if (gmReq && typeof gmReq.abort === 'function') { - req.abort = function() { - try { - return gmReq.abort(); - } catch (error) {} - }; - } - return req; - }, - cache: function(url, cb) { - return $.cache(url, cb, { - ajax: CrossOrigin.ajax - }); - }, - permission: function(cb) { - return cb(); - } - }; - - return CrossOrigin; - -}).call(this); - -Board = (function() { - var Board; - - Board = (function() { - Board.prototype.toString = function() { - return this.ID; - }; - - function Board(ID) { - var ref; - this.ID = ID; - this.boardID = this.ID; - this.siteID = g.SITE.ID; - this.threads = new SimpleDict(); - this.posts = new SimpleDict(); - this.config = ((ref = BoardConfig.boards) != null ? ref[this.ID] : void 0) || {}; - g.boards[this] = this; - } - - Board.prototype.cooldowns = function() { - var c, c2, i, key, len, ref; - c2 = (this.config || {}).cooldowns || {}; - c = { - thread: c2.threads || 0, - reply: c2.replies || 0, - image: c2.images || 0, - thread_global: 300 - }; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - ref = ['reply', 'image']; - for (i = 0, len = ref.length; i < len; i++) { - key = ref[i]; - c[key] = Math.ceil(c[key] / 2); - } - } - return c; - }; - - return Board; - - })(); - - return Board; - -}).call(this); - -Callbacks = (function() { - var Callbacks; - - Callbacks = (function() { - Callbacks.Post = new Callbacks('Post'); - - Callbacks.Thread = new Callbacks('Thread'); - - Callbacks.CatalogThread = new Callbacks('Catalog Thread'); - - Callbacks.CatalogThreadNative = new Callbacks('Catalog Thread'); - - function Callbacks(type) { - this.type = type; - this.keys = []; - } - - Callbacks.prototype.push = function(arg) { - var cb, name; - name = arg.name, cb = arg.cb; - if (!this[name]) { - this.keys.push(name); - } - return this[name] = cb; - }; - - Callbacks.prototype.execute = function(node, keys, force) { - var err, errors, i, len, name, ref, ref1, ref2; - if (keys == null) { - keys = this.keys; - } - if (force == null) { - force = false; - } - if (node.callbacksExecuted && !force) { - return; - } - node.callbacksExecuted = true; - for (i = 0, len = keys.length; i < len; i++) { - name = keys[i]; - try { - if ((ref = this[name]) != null) { - ref.call(node); - } - } catch (error) { - err = error; - if (!errors) { - errors = []; - } - errors.push({ - message: ['"', name, '" crashed on node ', this.type, ' No.', node.ID, ' (', node.board, ').'].join(''), - error: err, - html: (ref1 = node.nodes) != null ? (ref2 = ref1.root) != null ? ref2.outerHTML : void 0 : void 0 - }); - } - } - if (errors) { - return Main.handleErrors(errors); - } - }; - - return Callbacks; - - })(); - - return Callbacks; - -}).call(this); - -CatalogThread = (function() { - var CatalogThread; - - CatalogThread = (function() { - CatalogThread.prototype.toString = function() { - return this.ID; - }; - - function CatalogThread(root, thread) { - var post; - this.thread = thread; - this.ID = this.thread.ID; - this.board = this.thread.board; - post = this.thread.OP.nodes.post; - this.nodes = { - root: root, - thumb: $('.catalog-thumb', post), - icons: $('.catalog-icons', post), - postCount: $('.post-count', post), - fileCount: $('.file-count', post), - pageCount: $('.page-count', post), - replies: null - }; - this.thread.catalogView = this; - } - - return CatalogThread; - - })(); - - return CatalogThread; - -}).call(this); - -CatalogThreadNative = (function() { - var CatalogThreadNative; - - CatalogThreadNative = (function() { - CatalogThreadNative.prototype.toString = function() { - return this.ID; - }; - - function CatalogThreadNative(root) { - this.nodes = { - root: root, - thumb: $(g.SITE.selectors.catalog.thumb, root) - }; - this.siteID = g.SITE.ID; - this.boardID = this.nodes.thumb.parentNode.pathname.split(/\/+/)[1]; - this.board = g.boards[this.boardID] || new Board(this.boardID); - this.ID = this.threadID = +(root.dataset.id || root.id).match(/\d*$/)[0]; - this.thread = this.board.threads.get(this.ID) || new Thread(this.ID, this.board); - } - - return CatalogThreadNative; - - })(); - - return CatalogThreadNative; - -}).call(this); - -Connection = (function() { - var Connection, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - Connection = (function() { - function Connection(target, origin, cb) { - this.target = target; - this.origin = origin; - this.cb = cb != null ? cb : {}; - this.onMessage = bind(this.onMessage, this); - this.send = bind(this.send, this); - $.on(window, 'message', this.onMessage); - } - - Connection.prototype.targetWindow = function() { - if (this.target instanceof window.HTMLIFrameElement) { - return this.target.contentWindow; - } else { - return this.target; - } - }; - - Connection.prototype.send = function(data) { - return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); - }; - - Connection.prototype.onMessage = function(e) { - var data, type, value; - if (!(e.source === this.targetWindow() && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) { - return; - } - data = JSON.parse(e.data.slice(g.NAMESPACE.length)); - for (type in data) { - value = data[type]; - if ($.hasOwn(this.cb, type)) { - this.cb[type](value); - } - } - }; - - return Connection; - - })(); - - return Connection; - -}).call(this); - -DataBoard = (function() { - var DataBoard, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - DataBoard = (function() { - DataBoard.keys = ['hiddenThreads', 'hiddenPosts', 'lastReadPosts', 'yourPosts', 'watchedThreads', 'watcherLastModified', 'customTitles']; - - function DataBoard(key1, sync, dontClean) { - var init; - this.key = key1; - this.onSync = bind(this.onSync, this); - this.initData(Conf[this.key]); - $.sync(this.key, this.onSync); - if (!dontClean) { - this.clean(); - } - if (!sync) { - return; - } - init = (function(_this) { - return function() { - $.off(d, '4chanXInitFinished', init); - return _this.sync = sync; - }; - })(this); - $.on(d, '4chanXInitFinished', init); - } - - DataBoard.prototype.initData = function(data1) { - var base, boards, lastChecked, name, ref; - this.data = data1; - if (this.data.boards) { - ref = this.data, boards = ref.boards, lastChecked = ref.lastChecked; - this.data['4chan.org'] = { - boards: boards, - lastChecked: lastChecked - }; - delete this.data.boards; - delete this.data.lastChecked; - } - return (base = this.data)[name = g.SITE.ID] || (base[name] = { - boards: $.dict() - }); - }; - - DataBoard.prototype.changes = []; - - DataBoard.prototype.save = function(change, cb) { - change(); - this.changes.push(change); - return $.get(this.key, { - boards: $.dict() - }, (function(_this) { - return function(items) { - var i, len, needSync, ref; - if (!_this.changes.length) { - return; - } - needSync = (items[_this.key].version || 0) > (_this.data.version || 0); - if (needSync) { - _this.initData(items[_this.key]); - ref = _this.changes; - for (i = 0, len = ref.length; i < len; i++) { - change = ref[i]; - change(); - } - } - _this.changes = []; - _this.data.version = (_this.data.version || 0) + 1; - return $.set(_this.key, _this.data, function() { - if (needSync) { - if (typeof _this.sync === "function") { - _this.sync(); - } - } - return typeof cb === "function" ? cb() : void 0; - }); - }; - })(this)); - }; - - DataBoard.prototype.forceSync = function(cb) { - return $.get(this.key, { - boards: $.dict() - }, (function(_this) { - return function(items) { - var change, i, len, ref; - if ((items[_this.key].version || 0) > (_this.data.version || 0)) { - _this.initData(items[_this.key]); - ref = _this.changes; - for (i = 0, len = ref.length; i < len; i++) { - change = ref[i]; - change(); - } - if (typeof _this.sync === "function") { - _this.sync(); - } - } - return typeof cb === "function" ? cb() : void 0; - }; - })(this)); - }; - - DataBoard.prototype["delete"] = function(arg, cb) { - var boardID, postID, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID; - siteID || (siteID = g.SITE.ID); - if (!this.data[siteID]) { - return; - } - return this.save((function(_this) { - return function() { - var ref; - if (postID) { - if (!((ref = _this.data[siteID].boards[boardID]) != null ? ref[threadID] : void 0)) { - return; - } - delete _this.data[siteID].boards[boardID][threadID][postID]; - return _this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }); - } else if (threadID) { - if (!_this.data[siteID].boards[boardID]) { - return; - } - delete _this.data[siteID].boards[boardID][threadID]; - return _this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - } else { - return delete _this.data[siteID].boards[boardID]; - } - }; - })(this), cb); - }; - - DataBoard.prototype.deleteIfEmpty = function(arg) { - var boardID, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID; - if (!this.data[siteID]) { - return; - } - if (threadID) { - if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) { - delete this.data[siteID].boards[boardID][threadID]; - return this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - } - } else if (!Object.keys(this.data[siteID].boards[boardID]).length) { - return delete this.data[siteID].boards[boardID]; - } - }; - - DataBoard.prototype.set = function(data, cb) { - return this.save((function(_this) { - return function() { - return _this.setUnsafe(data); - }; - })(this), cb); - }; - - DataBoard.prototype.setUnsafe = function(arg) { - var base, base1, base2, base3, boardID, postID, siteID, threadID, val; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; - siteID || (siteID = g.SITE.ID); - (base = this.data)[siteID] || (base[siteID] = { - boards: $.dict() - }); - if (postID !== void 0) { - return ((base1 = ((base2 = this.data[siteID].boards)[boardID] || (base2[boardID] = $.dict())))[threadID] || (base1[threadID] = $.dict()))[postID] = val; - } else if (threadID !== void 0) { - return ((base3 = this.data[siteID].boards)[boardID] || (base3[boardID] = $.dict()))[threadID] = val; - } else { - return this.data[siteID].boards[boardID] = val; - } - }; - - DataBoard.prototype.extend = function(arg, cb) { - var boardID, postID, siteID, threadID, val; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; - return this.save((function(_this) { - return function() { - var key, oldVal, subVal; - oldVal = _this.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: postID, - defaultValue: $.dict() - }); - for (key in val) { - subVal = val[key]; - if (typeof subVal === 'undefined') { - delete oldVal[key]; - } else { - oldVal[key] = subVal; - } - } - return _this.setUnsafe({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: postID, - val: oldVal - }); - }; - })(this), cb); - }; - - DataBoard.prototype.setLastChecked = function(key) { - if (key == null) { - key = 'lastChecked'; - } - return this.save((function(_this) { - return function() { - return _this.data[key] = Date.now(); - }; - })(this)); - }; - - DataBoard.prototype.get = function(arg) { - var ID, board, boardID, defaultValue, i, len, postID, ref, siteID, thread, threadID, val; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; - siteID || (siteID = g.SITE.ID); - if (board = (ref = this.data[siteID]) != null ? ref.boards[boardID] : void 0) { - if (threadID == null) { - if (postID != null) { - for (thread = i = 0, len = board.length; i < len; thread = ++i) { - ID = board[thread]; - if (postID in thread) { - val = thread[postID]; - break; - } - } - } else { - val = board; - } - } else if (thread = board[threadID]) { - val = postID != null ? thread[postID] : thread; - } - } - return val || defaultValue; - }; - - DataBoard.prototype.clean = function() { - var boardID, now, ref, ref1, siteID, val; - siteID = g.SITE.ID; - ref = this.data[siteID].boards; - for (boardID in ref) { - val = ref[boardID]; - this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - } - now = Date.now(); - if (!((now - 2 * $.HOUR < (ref1 = this.data[siteID].lastChecked || 0) && ref1 <= now))) { - this.data[siteID].lastChecked = now; - for (boardID in this.data[siteID].boards) { - this.ajaxClean(boardID); - } - } - }; - - DataBoard.prototype.ajaxClean = function(boardID) { - var base, siteID, that, threadsList; - that = this; - siteID = g.SITE.ID; - threadsList = typeof (base = g.SITE.urls).threadsListJSON === "function" ? base.threadsListJSON({ - siteID: siteID, - boardID: boardID - }) : void 0; - if (!threadsList) { - return; - } - return $.cache(threadsList, function() { - var archiveList, base1, response1; - if (this.status !== 200) { - return; - } - archiveList = typeof (base1 = g.SITE.urls).archiveListJSON === "function" ? base1.archiveListJSON({ - siteID: siteID, - boardID: boardID - }) : void 0; - if (!archiveList) { - return that.ajaxCleanParse(boardID, this.response); - } - response1 = this.response; - return $.cache(archiveList, function() { - if (!(this.status === 200 || (!g.SITE.archivedBoardsKnown && this.status === 404))) { - return; - } - return that.ajaxCleanParse(boardID, response1, this.response); - }); - }); - }; - - DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { - var ID, board, i, j, k, len, len1, len2, page, ref, siteID, thread, threads; - siteID = g.SITE.ID; - if (!(board = this.data[siteID].boards[boardID])) { - return; - } - threads = $.dict(); - if (response1) { - for (i = 0, len = response1.length; i < len; i++) { - page = response1[i]; - ref = page.threads; - for (j = 0, len1 = ref.length; j < len1; j++) { - thread = ref[j]; - ID = thread.no; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - } - if (response2) { - for (k = 0, len2 = response2.length; k < len2; k++) { - ID = response2[k]; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - this.data[siteID].boards[boardID] = threads; - this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - return $.set(this.key, this.data); - }; - - DataBoard.prototype.onSync = function(data) { - if (!((data.version || 0) > (this.data.version || 0))) { - return; - } - this.initData(data); - return typeof this.sync === "function" ? this.sync() : void 0; - }; - - return DataBoard; - - })(); - - return DataBoard; - -}).call(this); - -Fetcher = (function() { - var Fetcher, - slice = [].slice; - - Fetcher = (function() { - function Fetcher(boardID1, threadID, postID1, root, quoter) { - var board, post, ref, that, thread; - this.boardID = boardID1; - this.threadID = threadID; - this.postID = postID1; - this.root = root; - this.quoter = quoter; - if (post = g.posts.get(this.boardID + "." + this.postID)) { - this.insert(post); - return; - } - if ((post = (ref = Index.replyData) != null ? ref[this.boardID + "." + this.postID] : void 0) && (thread = g.threads.get(this.boardID + "." + this.threadID))) { - board = g.boards[this.boardID]; - post = new Post(g.SITE.Build.postFromObject(post, this.boardID), thread, board, { - isFetchedQuote: true - }); - Main.callbackNodes('Post', [post]); - this.insert(post); - return; - } - this.root.textContent = "Loading post No." + this.postID + "..."; - if (this.threadID) { - that = this; - $.cache(g.SITE.urls.threadJSON({ - boardID: this.boardID, - threadID: this.threadID - }), function(arg) { - var isCached; - isCached = arg.isCached; - return that.fetchedPost(this, isCached); - }); - } else { - this.archivedPost(); - } - } - - Fetcher.prototype.insert = function(post) { - var boardID, clone, cssVersion, k, len, nodes, postID, quote, ref, ref1, ref2; - if (!this.root.parentNode) { - return; - } - this.quoter || (this.quoter = post); - clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); - Main.callbackNodes('Post', [clone]); - nodes = clone.nodes; - $.rmAll(nodes.root); - $.add(nodes.root, nodes.post); - ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); - for (k = 0, len = ref.length; k < len; k++) { - quote = ref[k]; - ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; - if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { - $.addClass(quote, 'forwardlink'); - } - } - if (clone.nodes.flag && !(Fetcher.flagCSS || (Fetcher.flagCSS = $('link[href^="//s.4cdn.org/css/flags."]')))) { - cssVersion = ((ref2 = $('link[href^="//s.4cdn.org/css/"]')) != null ? ref2.href.match(/\d+(?=\.css$)|$/)[0] : void 0) || Date.now(); - Fetcher.flagCSS = $.el('link', { - rel: 'stylesheet', - href: "//s.4cdn.org/css/flags." + cssVersion + ".css" - }); - $.add(d.head, Fetcher.flagCSS); - } - $.rmAll(this.root); - $.add(this.root, nodes.root); - return $.event('PostsInserted', null, this.root); - }; - - Fetcher.prototype.fetchedPost = function(req, isCached) { - var api, board, k, len, post, posts, status, that, thread; - if (post = g.posts.get(this.boardID + "." + this.postID)) { - this.insert(post); - return; - } - status = req.status; - if (status !== 200) { - if (status && this.archivedPost()) { - return; - } - $.addClass(this.root, 'warning'); - this.root.textContent = status === 404 ? "Thread No." + this.threadID + " 404'd." : !status ? 'Connection Error' : "Error " + req.statusText + " (" + req.status + ")."; - return; - } - posts = req.response.posts; - g.SITE.Build.spoilerRange[this.boardID] = posts[0].custom_spoiler; - for (k = 0, len = posts.length; k < len; k++) { - post = posts[k]; - if (post.no === this.postID) { - break; - } - } - if (post.no !== this.postID) { - if (isCached) { - api = g.SITE.urls.threadJSON({ - boardID: this.boardID, - threadID: this.threadID - }); - $.cleanCache(function(url) { - return url === api; - }); - that = this; - $.cache(api, function() { - return that.fetchedPost(this, false); - }); - return; - } - if (this.archivedPost()) { - return; - } - $.addClass(this.root, 'warning'); - this.root.textContent = "Post No." + this.postID + " was not found."; - return; - } - board = g.boards[this.boardID] || new Board(this.boardID); - thread = g.threads.get(this.boardID + "." + this.threadID) || new Thread(this.threadID, board); - post = new Post(g.SITE.Build.postFromObject(post, this.boardID), thread, board, { - isFetchedQuote: true - }); - Main.callbackNodes('Post', [post]); - return this.insert(post); - }; - - Fetcher.prototype.archivedPost = function() { - var archive, encryptionOK, that, url; - if (!Conf['Resurrect Quotes']) { - return false; - } - if (!(url = Redirect.to('post', { - boardID: this.boardID, - postID: this.postID - }))) { - return false; - } - archive = Redirect.data.post[this.boardID]; - encryptionOK = /^https:\/\//.test(url) || location.protocol === 'http:'; - if (encryptionOK || Conf['Exempt Archives from Encryption']) { - that = this; - CrossOrigin.cache(url, function() { - var key, media, ref, ref1; - if (!encryptionOK && ((ref = this.response) != null ? ref.media : void 0)) { - media = this.response.media; - for (key in media) { - if (/_link$/.test(key)) { - if (!((ref1 = $.getOwn(media, key)) != null ? ref1.match(/^http:\/\//) : void 0)) { - delete media[key]; - } - } - } - } - return that.parseArchivedPost(this.response, url, archive); - }); - return true; - } - return false; - }; - - Fetcher.prototype.parseArchivedPost = function(data, url, archive) { - var board, comment, greentext, i, j, media_link, o, post, ref, tag, text, text2, thread, thumb_link; - if (post = g.posts.get(this.boardID + "." + this.postID)) { - this.insert(post); - return; - } - if (data == null) { - $.addClass(this.root, 'warning'); - this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; - return; - } - if (data.error) { - $.addClass(this.root, 'warning'); - this.root.textContent = data.error; - return; - } - comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/); - comment = (function() { - var k, len, results; - results = []; - for (i = k = 0, len = comment.length; k < len; i = ++k) { - text = comment[i]; - if (i % 2 === 1) { - tag = this.archiveTags[text.replace(/\ .*\]/, ']')]; - if (typeof tag === 'function') { - results.push(tag(text)); - } else { - results.push(tag); - } - } else { - greentext = text[0] === '>'; - text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); - text = (function() { - var l, len1, ref, results1; - ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); - results1 = []; - for (j = l = 0, len1 = ref.length; l < len1; j = ++l) { - text2 = ref[j]; - results1.push({innerHTML: ((j % 2) ? "" + E(text2) + "" : E(text2))}); - } - return results1; - })(); - text = {innerHTML: ((greentext) ? "" + E.cat(text) + "" : E.cat(text))}; - results.push(text); - } - } - return results; - }).call(this); - comment = {innerHTML: E.cat(comment)}; - this.threadID = +data.thread_num; - o = { - ID: this.postID, - threadID: this.threadID, - boardID: this.boardID, - isReply: this.postID !== this.threadID - }; - o.info = { - subject: data.title, - email: data.email, - name: data.name || '', - tripcode: data.trip, - capcode: (function() { - switch (data.capcode) { - case 'M': - return 'Mod'; - case 'A': - return 'Admin'; - case 'D': - return 'Developer'; - case 'V': - return 'Verified'; - case 'F': - return 'Founder'; - case 'G': - return 'Manager'; - } - })(), - uniqueID: data.poster_hash, - flagCode: data.poster_country, - flagCodeTroll: data.troll_country_code, - flag: data.poster_country_name || data.troll_country_name, - dateUTC: data.timestamp, - dateText: data.fourchan_date, - commentHTML: comment - }; - if (o.info.capcode) { - delete o.info.uniqueID; - } - if (data.media && !!+data.media.banned) { - o.fileDeleted = true; - } else if ((ref = data.media) != null ? ref.media_filename : void 0) { - thumb_link = data.media.thumb_link; - if ((thumb_link != null ? thumb_link[0] : void 0) === '/') { - thumb_link = url.split('/', 3).join('/') + thumb_link; - } - if (!Redirect.securityCheck(thumb_link)) { - thumb_link = ''; - } - media_link = Redirect.to('file', { - boardID: this.boardID, - filename: data.media.media_orig - }); - if (!Redirect.securityCheck(media_link)) { - media_link = ''; - } - o.file = { - name: data.media.media_filename, - url: media_link || (this.boardID === 'f' ? location.protocol + "//" + (ImageHost.flashHost()) + "/" + this.boardID + "/" + (encodeURIComponent(E(data.media.media_filename))) : location.protocol + "//" + (ImageHost.host()) + "/" + this.boardID + "/" + data.media.media_orig), - height: data.media.media_h, - width: data.media.media_w, - MD5: data.media.media_hash, - size: $.bytesToString(data.media.media_size), - thumbURL: thumb_link || (location.protocol + "//" + (ImageHost.thumbHost()) + "/" + this.boardID + "/" + data.media.preview_orig), - theight: data.media.preview_h, - twidth: data.media.preview_w, - isSpoiler: data.media.spoiler === '1' - }; - if (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - if (this.boardID === 'f' && data.media.exif) { - o.file.tag = JSON.parse(data.media.exif).Tag; - } - } - o.extra = $.dict(); - board = g.boards[this.boardID] || new Board(this.boardID); - thread = g.threads.get(this.boardID + "." + this.threadID) || new Thread(this.threadID, board); - post = new Post(g.SITE.Build.post(o), thread, board, { - isFetchedQuote: true - }); - post.kill(); - if (post.file) { - post.file.thumbURL = o.file.thumbURL; - } - Main.callbackNodes('Post', [post]); - return this.insert(post); - }; - - Fetcher.prototype.archiveTags = { - '\n': {innerHTML: "
"}, - '[b]': {innerHTML: ""}, - '[/b]': {innerHTML: ""}, - '[spoiler]': {innerHTML: ""}, - '[/spoiler]': {innerHTML: ""}, - '[code]': {innerHTML: "
"},
-      '[/code]': {innerHTML: "
"}, - '[moot]': {innerHTML: "
"}, - '[/moot]': {innerHTML: "
"}, - '[banned]': {innerHTML: ""}, - '[/banned]': {innerHTML: ""}, - '[fortune]': function(text) { - return {innerHTML: ""}; - }, - '[/fortune]': {innerHTML: ""}, - '[i]': {innerHTML: ""}, - '[/i]': {innerHTML: ""}, - '[red]': {innerHTML: ""}, - '[/red]': {innerHTML: ""}, - '[green]': {innerHTML: ""}, - '[/green]': {innerHTML: ""}, - '[blue]': {innerHTML: ""}, - '[/blue]': {innerHTML: ""} - }; - - return Fetcher; - - })(); - - return Fetcher; - -}).call(this); - -Notice = (function() { - var Notice, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - Notice = (function() { - function Notice(type, content, timeout, onclose) { - this.timeout = timeout; - this.onclose = onclose; - this.close = bind(this.close, this); - this.add = bind(this.add, this); - this.el = $.el('div', {innerHTML: "
"}); - this.el.style.opacity = 0; - this.setType(type); - $.on(this.el.firstElementChild, 'click', this.close); - if (typeof content === 'string') { - content = $.tn(content); - } - $.add(this.el.lastElementChild, content); - $.ready(this.add); - } - - Notice.prototype.setType = function(type) { - return this.el.className = "notification " + type; - }; - - Notice.prototype.add = function() { - if (this.closed) { - return; - } - if (d.hidden) { - $.on(d, 'visibilitychange', this.add); - return; - } - $.off(d, 'visibilitychange', this.add); - $.add(Header.noticesRoot, this.el); - this.el.clientHeight; - this.el.style.opacity = 1; - if (this.timeout) { - return setTimeout(this.close, this.timeout * $.SECOND); - } - }; - - Notice.prototype.close = function() { - this.closed = true; - $.off(d, 'visibilitychange', this.add); - $.rm(this.el); - return typeof this.onclose === "function" ? this.onclose() : void 0; - }; - - return Notice; - - })(); - - return Notice; - -}).call(this); - -Post = (function() { - var Post, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Post = (function() { - Post.prototype.toString = function() { - return this.ID; - }; - - function Post(root, thread, board, flags) { - var clone, j, k, key, len, len1, ref, ref1, ref10, ref11, ref12, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, selector; - this.thread = thread; - this.board = board; - if (flags == null) { - flags = {}; - } - $.extend(this, flags); - this.ID = +root.id.match(/\d*$/)[0]; - this.postID = this.ID; - this.threadID = this.thread.ID; - this.boardID = this.board.ID; - this.siteID = g.SITE.ID; - this.fullID = this.board + "." + this.ID; - this.context = this; - this.isReply = this.ID !== this.threadID; - root.dataset.fullID = this.fullID; - this.nodes = this.parseNodes(root); - if (!this.isReply) { - this.thread.OP = this; - ref = ['isSticky', 'isClosed', 'isArchived']; - for (j = 0, len = ref.length; j < len; j++) { - key = ref[j]; - if ((selector = g.SITE.selectors.icons[key])) { - this.thread[key] = !!$(selector, this.nodes.info); - } - } - if (this.thread.isArchived) { - this.thread.isClosed = true; - this.thread.kill(); - } - } - this.info = { - subject: ((ref1 = this.nodes.subject) != null ? ref1.textContent : void 0) || void 0, - name: (ref2 = this.nodes.name) != null ? ref2.textContent : void 0, - email: this.nodes.email ? decodeURIComponent(this.nodes.email.href.replace(/^mailto:/, '')) : void 0, - tripcode: (ref3 = this.nodes.tripcode) != null ? ref3.textContent : void 0, - uniqueID: (ref4 = this.nodes.uniqueID) != null ? ref4.textContent : void 0, - capcode: (ref5 = this.nodes.capcode) != null ? ref5.textContent.replace('## ', '') : void 0, - pass: (ref6 = this.nodes.pass) != null ? ref6.title.match(/\d*$/)[0] : void 0, - flagCode: (ref7 = this.nodes.flag) != null ? (ref8 = ref7.className.match(/flag-(\w+)/)) != null ? ref8[1].toUpperCase() : void 0 : void 0, - flagCodeTroll: (ref9 = this.nodes.flag) != null ? (ref10 = ref9.className.match(/bfl-(\w+)/)) != null ? ref10[1].toUpperCase() : void 0 : void 0, - flag: (ref11 = this.nodes.flag) != null ? ref11.title : void 0, - date: this.nodes.date ? g.SITE.parseDate(this.nodes.date) : void 0 - }; - if (Conf['Anonymize']) { - this.info.nameBlock = 'Anonymous'; - } else { - this.info.nameBlock = ((this.info.name || '') + " " + (this.info.tripcode || '')).trim(); - } - if (this.info.capcode) { - this.info.nameBlock += " ## " + this.info.capcode; - } - if (this.info.uniqueID) { - this.info.nameBlock += " (ID: " + this.info.uniqueID + ")"; - } - this.parseComment(); - this.parseQuotes(); - this.parseFiles(); - this.isDead = false; - this.isHidden = false; - this.clones = []; - if (g.posts.get(this.fullID)) { - this.isRebuilt = true; - this.clones = g.posts.get(this.fullID).clones; - ref12 = this.clones; - for (k = 0, len1 = ref12.length; k < len1; k++) { - clone = ref12[k]; - clone.origin = this; - } - } - if (!this.isFetchedQuote && this.ID > this.thread.lastPost) { - this.thread.lastPost = this.ID; - } - this.board.posts.push(this.ID, this); - this.thread.posts.push(this.ID, this); - g.posts.push(this.fullID, this); - } - - Post.prototype.parseNodes = function(root) { - var base, info, key, nodes, post, ref, s, selector; - s = g.SITE.selectors; - post = $(s.post, root) || root; - info = $(s.infoRoot, post); - nodes = { - root: root, - bottom: this.isReply || !g.SITE.isOPContainerThread ? root : $(s.opBottom, root), - post: post, - info: info, - comment: $(s.comment, post), - quotelinks: [], - archivelinks: [], - embedlinks: [] - }; - ref = s.info; - for (key in ref) { - selector = ref[key]; - nodes[key] = $(selector, info); - } - if (typeof (base = g.SITE).parseNodes === "function") { - base.parseNodes(this, nodes); - } - nodes.uniqueIDRoot || (nodes.uniqueIDRoot = nodes.uniqueID); - if ($.engine === 'edge') { - Object.defineProperty(nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return post.getElementsByClassName('backlink'); - } - }); - } else { - nodes.backlinks = post.getElementsByClassName('backlink'); - } - return nodes; - }; - - Post.prototype.parseComment = function() { - var base, bq; - this.nodes.comment.normalize(); - this.nodes.commentClean = bq = this.nodes.comment.cloneNode(true); - if (typeof (base = g.SITE).cleanComment === "function") { - base.cleanComment(bq); - } - return this.info.comment = this.nodesToText(bq); - }; - - Post.prototype.commentDisplay = function() { - var base, bq; - bq = this.nodes.commentClean.cloneNode(true); - if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { - this.cleanSpoilers(bq); - } - if (typeof (base = g.SITE).cleanCommentDisplay === "function") { - base.cleanCommentDisplay(bq); - } - return this.nodesToText(bq).trim().replace(/\s+$/gm, ''); - }; - - Post.prototype.commentOrig = function() { - var base, bq; - bq = this.nodes.commentClean.cloneNode(true); - if (typeof (base = g.SITE).insertTags === "function") { - base.insertTags(bq); - } - return this.nodesToText(bq); - }; - - Post.prototype.nodesToText = function(bq) { - var i, node, nodes, text; - text = ""; - nodes = $.X('.//br|.//text()', bq); - i = 0; - while (node = nodes.snapshotItem(i++)) { - text += node.data || '\n'; - } - return text; - }; - - Post.prototype.cleanSpoilers = function(bq) { - var j, len, node, spoilers; - spoilers = $$(g.SITE.selectors.spoiler, bq); - for (j = 0, len = spoilers.length; j < len; j++) { - node = spoilers[j]; - $.replace(node, $.tn('[spoiler]')); - } - }; - - Post.prototype.parseQuotes = function() { - var j, len, quotelink, ref; - this.quotes = []; - ref = $$(g.SITE.selectors.quotelink, this.nodes.comment); - for (j = 0, len = ref.length; j < len; j++) { - quotelink = ref[j]; - this.parseQuote(quotelink); - } - }; - - Post.prototype.parseQuote = function(quotelink) { - var fullID, match; - match = quotelink.href.match(g.SITE.regexp.quotelink); - if (!(match || (this.isClone && quotelink.dataset.postID))) { - return; - } - this.nodes.quotelinks.push(quotelink); - if (this.isClone) { - return; - } - fullID = match[1] + "." + match[3]; - if (indexOf.call(this.quotes, fullID) < 0) { - return this.quotes.push(fullID); - } - }; - - Post.prototype.parseFiles = function() { - var docIndex, file, fileRoot, fileRoots, index, j, len; - this.files = []; - fileRoots = this.fileRoots(); - index = 0; - for (docIndex = j = 0, len = fileRoots.length; j < len; docIndex = ++j) { - fileRoot = fileRoots[docIndex]; - if ((file = this.parseFile(fileRoot))) { - file.index = index++; - file.docIndex = docIndex; - this.files.push(file); - } - } - if (this.files.length) { - return this.file = this.files[0]; - } - }; - - Post.prototype.fileRoots = function() { - var roots; - if (g.SITE.selectors.multifile) { - roots = $$(g.SITE.selectors.multifile, this.nodes.root); - if (roots.length) { - return roots; - } - } - return [this.nodes.root]; - }; - - Post.prototype.parseFile = function(fileRoot) { - var file, key, ref, ref1, selector, size, unit; - file = {}; - ref = g.SITE.selectors.file; - for (key in ref) { - selector = ref[key]; - file[key] = $(selector, fileRoot); - } - file.thumbLink = (ref1 = file.thumb) != null ? ref1.parentNode : void 0; - if (!(file.text && file.link)) { - return; - } - if (!g.SITE.parseFile(this, file)) { - return; - } - $.extend(file, { - url: file.link.href, - isImage: $.isImage(file.link.href), - isVideo: $.isVideo(file.link.href) - }); - size = +file.size.match(/[\d.]+/)[0]; - unit = ['B', 'KB', 'MB', 'GB'].indexOf(file.size.match(/\w+$/)[0]); - while (unit-- > 0) { - size *= 1024; - } - file.sizeInBytes = size; - return file; - }; - - Post.deadMark = $.el('span', { - textContent: '\u00A0(Dead)', - className: 'qmark-dead' - }); - - Post.prototype.kill = function(file, index) { - var clone, j, k, len, len1, quotelink, ref, ref1, strong; - if (index == null) { - index = 0; - } - if (file) { - if (this.isDead || this.files[index].isDead) { - return; - } - this.files[index].isDead = true; - $.addClass(this.nodes.root, 'deleted-file'); - } else { - if (this.isDead) { - return; - } - this.isDead = true; - $.rmClass(this.nodes.root, 'deleted-file'); - $.addClass(this.nodes.root, 'deleted-post'); - } - if (!(strong = $('strong.warning', this.nodes.info))) { - strong = $.el('strong', { - className: 'warning' - }); - $.after($('input', this.nodes.info), strong); - } - strong.textContent = file ? '[File deleted]' : '[Deleted]'; - if (this.isClone) { - return; - } - ref = this.clones; - for (j = 0, len = ref.length; j < len; j++) { - clone = ref[j]; - clone.kill(file, index); - } - if (file) { - return; - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (k = 0, len1 = ref1.length; k < len1; k++) { - quotelink = ref1[k]; - if (!(!$.hasClass(quotelink, 'deadlink'))) { - continue; - } - $.add(quotelink, Post.deadMark.cloneNode(true)); - $.addClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.resurrect = function() { - var clone, j, k, len, len1, quotelink, ref, ref1, strong; - this.isDead = false; - $.rmClass(this.nodes.root, 'deleted-post'); - strong = $('strong.warning', this.nodes.info); - if (this.files.some(function(file) { - return file.isDead; - })) { - $.addClass(this.nodes.root, 'deleted-file'); - strong.textContent = '[File deleted]'; - } else { - $.rm(strong); - } - if (this.isClone) { - return; - } - ref = this.clones; - for (j = 0, len = ref.length; j < len; j++) { - clone = ref[j]; - clone.resurrect(); - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (k = 0, len1 = ref1.length; k < len1; k++) { - quotelink = ref1[k]; - if (!($.hasClass(quotelink, 'deadlink'))) { - continue; - } - $.rm($('.qmark-dead', quotelink)); - $.rmClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.collect = function() { - g.posts.rm(this.fullID); - this.thread.posts.rm(this); - return this.board.posts.rm(this); - }; - - Post.prototype.addClone = function(context, contractThumb) { - Callbacks.Post.execute(this); - return new Post.Clone(this, context, contractThumb); - }; - - Post.prototype.rmClone = function(index) { - var clone, j, len, ref; - this.clones.splice(index, 1); - ref = this.clones.slice(index); - for (j = 0, len = ref.length; j < len; j++) { - clone = ref[j]; - clone.nodes.root.dataset.clone = index++; - } - }; - - Post.prototype.setCatalogOP = function(isCatalogOP) { - this.nodes.root.classList.toggle('catalog-container', isCatalogOP); - this.nodes.root.classList.toggle('opContainer', !isCatalogOP); - this.nodes.post.classList.toggle('catalog-post', isCatalogOP); - this.nodes.post.classList.toggle('op', !isCatalogOP); - return this.nodes.post.style.left = this.nodes.post.style.right = null; - }; - - return Post; - - })(); - - return Post; - -}).call(this); - -(function() { - var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, - hasProp = {}.hasOwnProperty, - slice = [].slice; - - Post.Clone = (function(superClass) { - extend(_Class, superClass); - - _Class.prototype.isClone = true; - - function _Class() { - var that; - that = Object.create(Post.Clone.prototype); - that.construct.apply(that, arguments); - return that; - } - - _Class.prototype.construct = function(origin, context, contractThumb) { - var base, file, fileRoot, fileRoots, i, inline, inlined, j, k, key, l, len, len1, len2, len3, len4, m, node, nodes, originFile, ref, ref1, ref2, ref3, ref4, ref5, ref6, root, selector, val; - this.origin = origin; - this.context = context; - ref = ['ID', 'postID', 'threadID', 'boardID', 'siteID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply']; - for (i = 0, len = ref.length; i < len; i++) { - key = ref[i]; - this[key] = this.origin[key]; - } - nodes = this.origin.nodes; - root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); - (base = Post.Clone).suffix || (base.suffix = 0); - ref1 = [root].concat(slice.call($$('[id]', root))); - for (j = 0, len1 = ref1.length; j < len1; j++) { - node = ref1[j]; - node.id += "_" + Post.Clone.suffix; - } - Post.Clone.suffix++; - ref2 = $$('.inline', root); - for (k = 0, len2 = ref2.length; k < len2; k++) { - inline = ref2[k]; - $.rm(inline); - } - ref3 = $$('.inlined', root); - for (l = 0, len3 = ref3.length; l < len3; l++) { - inlined = ref3[l]; - $.rmClass(inlined, 'inlined'); - } - this.nodes = this.parseNodes(root); - root.hidden = false; - $.rmClass(root, 'forwarded'); - $.rmClass(this.nodes.post, 'highlight'); - if (!this.isReply) { - this.setCatalogOP(false); - $.rm($('.catalog-link', this.nodes.post)); - $.rm($('.catalog-stats', this.nodes.post)); - $.rm($('.catalog-replies', this.nodes.post)); - } - this.parseQuotes(); - this.quotes = slice.call(this.origin.quotes); - this.files = []; - if (this.origin.files.length) { - fileRoots = this.fileRoots(); - } - ref4 = this.origin.files; - for (m = 0, len4 = ref4.length; m < len4; m++) { - originFile = ref4[m]; - file = {}; - for (key in originFile) { - val = originFile[key]; - file[key] = val; - } - fileRoot = fileRoots[file.docIndex]; - ref5 = g.SITE.selectors.file; - for (key in ref5) { - selector = ref5[key]; - file[key] = $(selector, fileRoot); - } - file.thumbLink = (ref6 = file.thumb) != null ? ref6.parentNode : void 0; - if (file.thumbLink) { - file.fullImage = $('.full-image', file.thumbLink); - } - file.videoControls = $('.video-controls', file.text); - if (file.videoThumb) { - file.thumb.muted = true; - } - this.files.push(file); - } - if (this.files.length) { - this.file = this.files[0]; - if (this.file.thumb && contractThumb) { - ImageExpand.contract(this); - } - } - if (this.origin.isDead) { - this.isDead = true; - } - return root.dataset.clone = this.origin.clones.push(this) - 1; - }; - - _Class.prototype.cloneWithoutVideo = function(node) { - var child, clone, i, len, ref; - if (node.tagName === 'VIDEO' && !node.dataset.md5) { - return []; - } else if (node.nodeType === Node.ELEMENT_NODE && $('video', node)) { - clone = node.cloneNode(false); - ref = node.childNodes; - for (i = 0, len = ref.length; i < len; i++) { - child = ref[i]; - $.add(clone, this.cloneWithoutVideo(child)); - } - return clone; - } else { - return node.cloneNode(true); - } - }; - - return _Class; - - })(Post); - -}).call(this); - -RandomAccessList = (function() { - var RandomAccessList; - - RandomAccessList = (function() { - function RandomAccessList(items) { - var i, item, len; - this.length = 0; - if (items) { - for (i = 0, len = items.length; i < len; i++) { - item = items[i]; - this.push(item); - } - } - } - - RandomAccessList.prototype.push = function(data) { - var ID, item, last; - ID = data.ID; - ID || (ID = data.id); - if (this[ID]) { - return; - } - last = this.last; - this[ID] = item = { - prev: last, - next: null, - data: data, - ID: ID - }; - item.prev = last; - this.last = last ? last.next = item : this.first = item; - return this.length++; - }; - - RandomAccessList.prototype.before = function(root, item) { - var prev; - if (item.next === root || item === root) { - return; - } - this.rmi(item); - prev = root.prev; - root.prev = item; - item.next = root; - item.prev = prev; - if (prev) { - return prev.next = item; - } else { - return this.first = item; - } - }; - - RandomAccessList.prototype.after = function(root, item) { - var next; - if (item.prev === root || item === root) { - return; - } - this.rmi(item); - next = root.next; - root.next = item; - item.prev = root; - item.next = next; - if (next) { - return next.prev = item; - } else { - return this.last = item; - } - }; - - RandomAccessList.prototype.prepend = function(item) { - var first; - first = this.first; - if (item === first || !this[item.ID]) { - return; - } - this.rmi(item); - item.next = first; - if (first) { - first.prev = item; - } else { - this.last = item; - } - this.first = item; - return delete item.prev; - }; - - RandomAccessList.prototype.shift = function() { - return this.rm(this.first.ID); - }; - - RandomAccessList.prototype.order = function() { - var item, order; - order = [item = this.first]; - while (item = item.next) { - order.push(item); - } - return order; - }; - - RandomAccessList.prototype.rm = function(ID) { - var item; - item = this[ID]; - if (!item) { - return; - } - delete this[ID]; - this.length--; - this.rmi(item); - delete item.next; - return delete item.prev; - }; - - RandomAccessList.prototype.rmi = function(item) { - var next, prev; - prev = item.prev, next = item.next; - if (prev) { - prev.next = next; - } else { - this.first = next; - } - if (next) { - return next.prev = prev; - } else { - return this.last = prev; - } - }; - - return RandomAccessList; - - })(); - - return RandomAccessList; - -}).call(this); - -ShimSet = (function() { - var ShimSet; - - ShimSet = (function() { - function ShimSet() { - this.elements = $.dict(); - this.size = 0; - } - - ShimSet.prototype.has = function(value) { - return value in this.elements; - }; - - ShimSet.prototype.add = function(value) { - if (this.elements[value]) { - return; - } - this.elements[value] = true; - return this.size++; - }; - - ShimSet.prototype["delete"] = function(value) { - if (!this.elements[value]) { - return; - } - delete this.elements[value]; - return this.size--; - }; - - return ShimSet; - - })(); - - if (!('Set' in window)) { - window.Set = ShimSet; - } - - return ShimSet; - -}).call(this); - -SimpleDict = (function() { - var SimpleDict, - slice = [].slice; - - SimpleDict = (function() { - function SimpleDict() { - this.keys = []; - } - - SimpleDict.prototype.push = function(key, data) { - key = "" + key; - if (!this[key]) { - this.keys.push(key); - } - return this[key] = data; - }; - - SimpleDict.prototype.rm = function(key) { - var i; - key = "" + key; - if ((i = this.keys.indexOf(key)) !== -1) { - this.keys.splice(i, 1); - return delete this[key]; - } - }; - - SimpleDict.prototype.forEach = function(fn) { - var j, key, len, ref; - ref = slice.call(this.keys); - for (j = 0, len = ref.length; j < len; j++) { - key = ref[j]; - fn(this[key]); - } - }; - - SimpleDict.prototype.get = function(key) { - if (key === 'keys') { - return void 0; - } else { - return $.getOwn(this, key); - } - }; - - return SimpleDict; - - })(); - - return SimpleDict; - -}).call(this); - -Thread = (function() { - var Thread; - - Thread = (function() { - Thread.prototype.toString = function() { - return this.ID; - }; - - function Thread(ID, board) { - this.board = board; - this.ID = +ID; - this.threadID = this.ID; - this.boardID = this.board.ID; - this.siteID = g.SITE.ID; - this.fullID = this.board + "." + this.ID; - this.posts = new SimpleDict(); - this.isDead = false; - this.isHidden = false; - this.isSticky = false; - this.isClosed = false; - this.isArchived = false; - this.postLimit = false; - this.fileLimit = false; - this.lastPost = 0; - this.ipCount = void 0; - this.json = null; - this.OP = null; - this.catalogView = null; - this.nodes = { - root: null - }; - this.board.threads.push(this.ID, this); - g.threads.push(this.fullID, this); - } - - Thread.prototype.setPage = function(pageNum) { - var icon, info, ref, reply; - ref = this.OP.nodes, info = ref.info, reply = ref.reply; - if (!(icon = $('.page-num', info))) { - icon = $.el('span', { - className: 'page-num' - }); - $.replace(reply.parentNode.previousSibling, [$.tn(' '), icon, $.tn(' ')]); - } - icon.title = "This thread is on page " + pageNum + " in the original index."; - icon.textContent = "[" + pageNum + "]"; - if (this.catalogView) { - return this.catalogView.nodes.pageCount.textContent = pageNum; - } - }; - - Thread.prototype.setCount = function(type, count, reachedLimit) { - var el; - if (!this.catalogView) { - return; - } - el = this.catalogView.nodes[type + "Count"]; - el.textContent = count; - return (reachedLimit ? $.addClass : $.rmClass)(el, 'warning'); - }; - - Thread.prototype.setStatus = function(type, status) { - var name; - name = "is" + type; - if (this[name] === status) { - return; - } - this[name] = status; - if (!this.OP) { - return; - } - this.setIcon('Sticky', this.isSticky); - this.setIcon('Closed', this.isClosed && !this.isArchived); - return this.setIcon('Archived', this.isArchived); - }; - - Thread.prototype.setIcon = function(type, status) { - var icon, root, typeLC; - typeLC = type.toLowerCase(); - icon = $("." + typeLC + "Icon", this.OP.nodes.info); - if (!!icon === status) { - return; - } - if (!status) { - $.rm(icon.previousSibling); - $.rm(icon); - if (this.catalogView) { - $.rm($("." + typeLC + "Icon", this.catalogView.nodes.icons)); - } - return; - } - icon = $.el('img', { - src: "" + g.SITE.Build.staticPath + typeLC + g.SITE.Build.gifIcon, - alt: type, - title: type, - className: typeLC + "Icon retina" - }); - if (g.BOARD.ID === 'f') { - icon.style.cssText = 'height: 18px; width: 18px;'; - } - root = type !== 'Sticky' && this.isSticky ? $('.stickyIcon', this.OP.nodes.info) : $('.page-num', this.OP.nodes.info) || this.OP.nodes.quote; - $.after(root, [$.tn(' '), icon]); - if (!this.catalogView) { - return; - } - return (type === 'Sticky' && this.isClosed ? $.prepend : $.add)(this.catalogView.nodes.icons, icon.cloneNode()); - }; - - Thread.prototype.kill = function() { - return this.isDead = true; - }; - - Thread.prototype.collect = function() { - var n; - n = 0; - this.posts.forEach(function(post) { - if (post.clones.length) { - return n++; - } else { - return post.collect(); - } - }); - if (!n) { - g.threads.rm(this.fullID); - return this.board.threads.rm(this); - } - }; - - return Thread; - - })(); - - return Thread; - -}).call(this); - -SW = {}; - -(function() { - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - SW.tinyboard = { - isOPContainerThread: true, - mayLackJSON: true, - threadModTimeIgnoresSage: true, - disabledFeatures: ['Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Report Link', 'Delete Link', 'Edit Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Quote Threading', 'Thread Updater', 'Banner', 'Flash Features', 'Reply Pruning'], - detect: function() { - var j, len, m, properties, ref, root, script; - ref = $$('script:not([src])', d.head); - for (j = 0, len = ref.length; j < len; j++) { - script = ref[j]; - if ((m = script.textContent.match(/\bvar configRoot=(".*?")/))) { - properties = $.dict(); - try { - root = JSON.parse(m[1]); - if (root[0] === '/') { - properties.root = location.origin + root; - } else if (/^https?:/.test(root)) { - properties.root = root; - } - } catch (error) {} - return properties; - } - } - return false; - }, - awaitBoard: function(cb) { - var reactUI, s; - if ((reactUI = $.id('react-ui'))) { - s = this.selectors = Object.create(this.selectors); - s.boardFor = { - index: '.page-container' - }; - s.thread = 'div[id^="thread_"]'; - return Main.mounted(cb); - } else { - return cb(); - } - }, - urls: { - thread: function(arg, isArchived) { - var boardID, ref, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/" + (isArchived ? 'archive/' : '') + "res/" + threadID + ".html"; - }, - post: function(arg) { - var postID; - postID = arg.postID; - return "#" + postID; - }, - index: function(arg) { - var boardID, ref, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/"; - }, - catalog: function(arg) { - var boardID, ref, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/catalog.html"; - }, - threadJSON: function(arg, isArchived) { - var boardID, ref, root, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/" + (isArchived ? 'archive/' : '') + "res/" + threadID + ".json"; - } else { - return ''; - } - }, - archivedThreadJSON: function(thread) { - return SW.tinyboard.urls.threadJSON(thread, true); - }, - threadsListJSON: function(arg) { - var boardID, ref, root, siteID; - siteID = arg.siteID, boardID = arg.boardID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/threads.json"; - } else { - return ''; - } - }, - archiveListJSON: function(arg) { - var boardID, ref, root, siteID; - siteID = arg.siteID, boardID = arg.boardID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/archive/archive.json"; - } else { - return ''; - } - }, - catalogJSON: function(arg) { - var boardID, ref, root, siteID; - siteID = arg.siteID, boardID = arg.boardID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/catalog.json"; - } else { - return ''; - } - }, - file: function(arg, filename) { - var boardID, ref, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/" + filename; - }, - thumb: function(board, filename) { - return SW.tinyboard.urls.file(board, filename); - } - }, - selectors: { - board: 'form[name="postcontrols"]', - thread: 'input[name="board"] ~ div[id^="thread_"]', - threadDivider: 'div[id^="thread_"] > hr:last-child', - summary: '.omitted', - postContainer: 'div[id^="reply_"]:not(.hidden)', - opBottom: '.op', - replyOriginal: 'div[id^="reply_"]:not(.hidden)', - infoRoot: '.intro', - info: { - subject: '.subject', - name: '.name', - email: '.email', - tripcode: '.trip', - uniqueID: '.poster_id', - capcode: '.capcode', - flag: '.flag', - date: 'time', - nameBlock: 'label', - quote: 'a[href*="#q"]', - reply: 'a[href*="/res/"]:not([href*="#"])' - }, - icons: { - isSticky: '.fa-thumb-tack', - isClosed: '.fa-lock' - }, - file: { - text: '.fileinfo', - link: '.fileinfo > a', - thumb: 'a > .post-image' - }, - thumbLink: '.file > a', - multifile: '.files > .file', - highlightable: { - op: ' > .op', - reply: '.reply', - catalog: ' > .thread' - }, - comment: '.body', - spoiler: '.spoiler', - quotelink: 'a[onclick*="highlightReply("]', - catalog: { - board: '#Grid', - thread: '.mix', - thumb: '.thread-image' - }, - boardList: '.boardlist', - boardListBottom: '.boardlist.bottom', - styleSheet: '#stylesheet', - psa: '.blotter', - nav: { - prev: '.pages > form > [value=Previous]', - next: '.pages > form > [value=Next]' - } - }, - classes: { - highlight: 'highlighted' - }, - xpath: { - thread: 'div[starts-with(@id,"thread_")]', - postContainer: 'div[starts-with(@id,"reply_") or starts-with(@id,"thread_")]', - replyContainer: 'div[starts-with(@id,"reply_")]' - }, - regexp: { - quotelink: /\/([^\/]+)\/res\/(\d+)(?:\.\w+)?#(\d+)$/, - quotelinkHTML: /]*\bhref="[^"]*\/([^\/]+)\/res\/(\d+)(?:\.\w+)?#(\d+)"/g - }, - Build: { - parseJSON: function(data, board) { - var extra_file, file, i, j, len, o, ref; - o = SW.yotsuba.Build.parseJSON(data, board); - if (data.ext === 'deleted') { - delete o.file; - $.extend(o, { - files: [], - fileDeleted: true, - filesDeleted: [0] - }); - } - if (data.extra_files) { - ref = data.extra_files; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - extra_file = ref[i]; - if (extra_file.ext === 'deleted') { - o.filesDeleted.push(i); - } else { - file = SW.yotsuba.Build.parseJSONFile(data, board); - o.files.push(file); - } - } - if (o.files.length) { - o.file = o.files[0]; - } - } - return o; - }, - parseComment: function(html) { - html = html.replace(//gi, '\n').replace(/<[^>]*>/g, ''); - return $.unescape(html); - } - }, - bgColoredEl: function() { - return $.el('div', { - className: 'post reply' - }); - }, - isFileURL: function(url) { - return /\/src\/[^\/]+/.test(url.pathname); - }, - preParsingFixes: function(board) { - var broken; - if ((broken = $('a > input[name="board"]', board))) { - return $.before(broken.parentNode, broken); - } - }, - parseNodes: function(post, nodes) { - var m, nextSibling, node, text, uniqueID; - if (nodes.uniqueID) { - return; - } - text = ''; - node = nodes.nameBlock.nextSibling; - while (node && node.nodeType === 3) { - text += node.textContent; - node = node.nextSibling; - } - if ((m = text.match(/(\s*ID:\s*)(\S+)/))) { - nodes.info.normalize(); - nextSibling = nodes.nameBlock.nextSibling; - nextSibling = nextSibling.splitText(m[1].length); - nextSibling.splitText(m[2].length); - nodes.uniqueID = uniqueID = $.el('span', { - className: 'poster_id' - }); - $.replace(nextSibling, uniqueID); - return $.add(uniqueID, nextSibling); - } - }, - parseDate: function(node) { - var date, ref; - date = Date.parse((ref = node.getAttribute('datetime')) != null ? ref.trim() : void 0); - if (!isNaN(date)) { - return new Date(date); - } - date = Date.parse(node.textContent.trim() + ' UTC'); - if (!isNaN(date)) { - return new Date(date); - } - return void 0; - }, - parseFile: function(post, file) { - var info, infoNode, link, nameNode, ref, ref1, text, thumb; - text = file.text, link = file.link, thumb = file.thumb; - if ($.x("ancestor::" + this.xpath.postContainer + "[1]", text) !== post.nodes.root) { - return false; - } - if (!(infoNode = indexOf.call((ref = link.nextSibling) != null ? ref.textContent : void 0, '(') >= 0 ? link.nextSibling : link.nextElementSibling)) { - return false; - } - if (!(info = infoNode.textContent.match(/\((.*,\s*)?([\d.]+ ?[KMG]?B).*\)/))) { - return false; - } - nameNode = $('.postfilename', text); - $.extend(file, { - name: nameNode ? nameNode.title || nameNode.textContent : link.pathname.match(/[^\/]*$/)[0], - size: info[2], - dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0 - }); - if (thumb) { - $.extend(file, { - thumbURL: /\/static\//.test(thumb.src) && $.isImage(link.href) ? link.href : thumb.src, - isSpoiler: /^Spoiler/i.test(info[1] || '') || link.textContent === 'Spoiler Image' - }); - } - return true; - }, - isThumbExpanded: function(file) { - return $.hasClass(file.thumb.parentNode, 'expanded') || file.thumb.parentNode.dataset.expanded === 'true'; - }, - isLinkified: function(link) { - return /\bnofollow\b/.test(link.rel); - }, - catalogPin: function(threadRoot) { - return threadRoot.dataset.sticky = 'true'; - } - }; - -}).call(this); - -(function() { - var slice = [].slice; - - SW.yotsuba = { - isOPContainerThread: false, - hasIPCount: true, - archivedBoardsKnown: true, - urls: { - thread: function(arg) { - var boardID, threadID; - boardID = arg.boardID, threadID = arg.threadID; - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/thread/" + threadID; - }, - post: function(arg) { - var postID; - postID = arg.postID; - return "#p" + postID; - }, - index: function(arg) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/"; - }, - catalog: function(arg) { - var boardID; - boardID = arg.boardID; - if (boardID === 'f') { - return void 0; - } else { - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/catalog"; - } - }, - archive: function(arg) { - var boardID; - boardID = arg.boardID; - if (BoardConfig.isArchived(boardID)) { - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/archive"; - } else { - return void 0; - } - }, - threadJSON: function(arg) { - var boardID, threadID; - boardID = arg.boardID, threadID = arg.threadID; - return location.protocol + "//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json"; - }, - threadsListJSON: function(arg) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//a.4cdn.org/" + boardID + "/threads.json"; - }, - archiveListJSON: function(arg) { - var boardID; - boardID = arg.boardID; - if (BoardConfig.isArchived(boardID)) { - return location.protocol + "//a.4cdn.org/" + boardID + "/archive.json"; - } else { - return ''; - } - }, - catalogJSON: function(arg) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//a.4cdn.org/" + boardID + "/catalog.json"; - }, - file: function(arg, filename) { - var boardID, hostname; - boardID = arg.boardID; - hostname = boardID === 'f' ? ImageHost.flashHost() : ImageHost.host(); - return location.protocol + "//" + hostname + "/" + boardID + "/" + filename; - }, - thumb: function(arg, filename) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//" + (ImageHost.thumbHost()) + "/" + boardID + "/" + filename; - } - }, - isPrunedByAge: function(arg) { - var boardID; - boardID = arg.boardID; - return boardID === 'f'; - }, - areMD5sDeferred: function(arg) { - var boardID; - boardID = arg.boardID; - return boardID === 'f'; - }, - isOnePage: function(arg) { - var boardID; - boardID = arg.boardID; - return boardID === 'f'; - }, - noAudio: function(arg) { - var boardID; - boardID = arg.boardID; - return BoardConfig.noAudio(boardID); - }, - selectors: { - board: '.board', - thread: '.thread', - threadDivider: '.board > hr', - summary: '.summary', - postContainer: '.postContainer', - replyOriginal: '.replyContainer:not([data-clone])', - sideArrows: 'div.sideArrows', - post: '.post', - infoRoot: '.postInfo', - info: { - subject: '.subject', - name: '.name', - email: '.useremail', - tripcode: '.postertrip', - uniqueIDRoot: '.posteruid', - uniqueID: '.posteruid > .hand', - capcode: '.capcode.hand', - pass: '.n-pu', - flag: '.flag, .bfl', - date: '.dateTime', - nameBlock: '.nameBlock', - quote: '.postNum > a:nth-of-type(2)', - reply: '.replylink' - }, - icons: { - isSticky: '.stickyIcon', - isClosed: '.closedIcon', - isArchived: '.archivedIcon' - }, - file: { - text: '.file > :first-child', - link: '.fileText > a', - thumb: 'a.fileThumb > [data-md5]' - }, - thumbLink: 'a.fileThumb', - highlightable: { - op: '.opContainer', - reply: ' > .reply', - catalog: '' - }, - comment: '.postMessage', - spoiler: 's', - quotelink: ':not(pre) > .quotelink', - catalog: { - board: '#threads', - thread: '.thread', - thumb: '.thumb' - }, - boardList: '#boardNavDesktop > .boardList', - boardListBottom: '#boardNavDesktopFoot > .boardList', - styleSheet: 'link[title=switch]', - psa: '#globalMessage', - psaTop: '#globalToggle', - searchBox: '#search-box', - nav: { - prev: '.prev > form > [type=submit]', - next: '.next > form > [type=submit]' - } - }, - classes: { - highlight: 'highlight' - }, - xpath: { - thread: 'div[contains(concat(" ",@class," ")," thread ")]', - postContainer: 'div[contains(@class,"postContainer")]', - replyContainer: 'div[contains(@class,"replyContainer")]' - }, - regexp: { - quotelink: /^https?:\/\/boards\.4chan(?:nel)?\.org\/+([^\/]+)\/+thread\/+(\d+)(?:[\/?][^#]*)?(?:#p(\d+))?$/, - quotelinkHTML: /]*\bhref="(?:(?:\/\/boards\.4chan(?:nel)?\.org)?\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g, - pass: /^https?:\/\/www\.4chan(?:nel)?\.org\/+pass(?:$|[?#])/, - captcha: /^https?:\/\/sys\.4chan(?:nel)?\.org\/+captcha(?:$|[?#])/ - }, - bgColoredEl: function() { - return $.el('div', { - className: 'reply' - }); - }, - isThisPageLegit: function() { - var ref, ref1; - return ((ref = location.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') && d.doctype && !$('link[href*="favicon-status.ico"]', d.head) && ((ref1 = d.title) !== '4chan - Temporarily Offline' && ref1 !== '4chan - Error' && ref1 !== '504 Gateway Time-out' && ref1 !== 'MathJax Equation Source'); - }, - is404: function() { - var ref; - return ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || (g.VIEW === 'thread' && $('.board') && !$('.opContainer')); - }, - isIncomplete: function() { - var ref; - return ((ref = g.VIEW) === 'index' || ref === 'thread') && !$('.board + *'); - }, - isBoardlessPage: function(url) { - var ref; - return (ref = url.hostname) === 'www.4chan.org' || ref === 'www.4channel.org'; - }, - isAuxiliaryPage: function(url) { - var ref; - return (ref = url.hostname) !== 'boards.4chan.org' && ref !== 'boards.4channel.org'; - }, - isFileURL: function(url) { - return ImageHost.test(url.hostname); - }, - initAuxiliary: function() { - var match, pathname; - switch (location.hostname) { - case 'www.4chan.org': - case 'www.4channel.org': - if (SW.yotsuba.regexp.pass.test(location.href)) { - PassMessage.init(); - } else { - $.onExists(doc, 'body', function() { - return $.addStyle(CSS.www); - }); - Captcha.replace.init(); - } - break; - case 'sys.4chan.org': - case 'sys.4channel.org': - pathname = location.pathname.split(/\/+/); - if (pathname[2] === 'imgboard.php') { - if (/\bmode=report\b/.test(location.search)) { - Report.init(); - } else if ((match = location.search.match(/\bres=(\d+)/))) { - $.ready(function() { - var ref; - if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - postID: +match[1] - }); - } - }); - } - } else if (pathname[2] === 'post') { - PostSuccessful.init(); - } - } - }, - scriptData: function() { - var j, len, ref, script; - ref = $$('script:not([src])', d.head); - for (j = 0, len = ref.length; j < len; j++) { - script = ref[j]; - if (/\bcooldowns *=/.test(script.textContent)) { - return script.textContent; - } - } - return ''; - }, - parseThreadMetadata: function(thread) { - var file, m, scriptData; - scriptData = this.scriptData(); - thread.postLimit = /\bbumplimit *= *1\b/.test(scriptData); - thread.fileLimit = /\bimagelimit *= *1\b/.test(scriptData); - thread.ipCount = (m = scriptData.match(/\bunique_ips *= *(\d+)\b/)) ? +m[1] : void 0; - if (g.BOARD.ID === 'f' && thread.OP.file) { - file = thread.OP.file; - return $.ajax(this.urls.threadJSON({ - boardID: 'f', - threadID: thread.ID - }), { - timeout: $.MINUTE, - onloadend: function() { - if (this.response) { - return file.text.dataset.md5 = file.MD5 = this.response.posts[0].md5; - } - } - }); - } - }, - parseNodes: function(post, nodes) { - var icon, j, len, ref, results, type; - if (post.boardID === 'f') { - ref = ['Sticky', 'Closed']; - results = []; - for (j = 0, len = ref.length; j < len; j++) { - type = ref[j]; - if ((icon = $("img[alt=" + type + "]", nodes.info))) { - results.push($.addClass(icon, (type.toLowerCase()) + "Icon", 'retina')); - } - } - return results; - } - }, - parseDate: function(node) { - return new Date(node.dataset.utc * 1000); - }, - parseFile: function(post, file) { - var info, link, m, ref, ref1, ref2, text, thumb; - text = file.text, link = file.link, thumb = file.thumb; - if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { - return false; - } - $.extend(file, { - name: text.title || link.title || link.textContent, - size: info[1], - dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, - tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0, - MD5: text.dataset.md5 - }); - if (thumb) { - $.extend(file, { - thumbURL: thumb.src, - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') - }); - if (file.isSpoiler) { - file.thumbURL = (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//" + (ImageHost.thumbHost()) + "/" + post.board + "/" + m[0] + "s.jpg" : void 0; - } - } - return true; - }, - cleanComment: function(bq) { - var abbr, br, i, j, k, len, node, ref; - if ((abbr = $('.abbr', bq))) { - ref = $$('.abbr + br, .exif', bq); - for (j = 0, len = ref.length; j < len; j++) { - node = ref[j]; - $.rm(node); - } - for (i = k = 0; k < 2; i = ++k) { - if ((br = abbr.previousSibling) && br.nodeName === 'BR') { - $.rm(br); - } - } - return $.rm(abbr); - } - }, - cleanCommentDisplay: function(bq) { - var b; - if ((b = $('b', bq)) && /^Rolled /.test(b.textContent)) { - $.rm(b); - } - return $.rm($('.fortune', bq)); - }, - insertTags: function(bq) { - var j, k, len, len1, node, ref, ref1; - ref = $$('s, .removed-spoiler', bq); - for (j = 0, len = ref.length; j < len; j++) { - node = ref[j]; - $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); - } - ref1 = $$('.prettyprint', bq); - for (k = 0, len1 = ref1.length; k < len1; k++) { - node = ref1[k]; - $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); - } - }, - hasCORS: function(url) { - return url.split('/').slice(0, 3).join('/') === location.protocol + '//a.4cdn.org'; - }, - sfwBoards: function(sfw) { - return BoardConfig.sfwBoards(sfw); - }, - uidColor: function(uid) { - var i, msg; - msg = 0; - i = 0; - while (i < 8) { - msg = (msg << 5) - msg + uid.charCodeAt(i++); - } - return (msg >> 8) & 0xFFFFFF; - }, - isLinkified: function(link) { - return ImageHost.test(link.hostname); - }, - testNativeExtension: function() { - return $.global(function() { - if (window.Parser.postMenuIcon) { - return this.enabled = 'true'; - } - }); - }, - transformBoardList: function() { - var a, chr, i, items, j, len, node, nodes, ref, spacer, span; - nodes = []; - spacer = function() { - return $.el('span', { - className: 'spacer' - }); - }; - items = $.X('.//a|.//text()[not(ancestor::a)]', $(SW.yotsuba.selectors.boardList)); - i = 0; - while (node = items.snapshotItem(i++)) { - switch (node.nodeName) { - case '#text': - ref = node.nodeValue; - for (j = 0, len = ref.length; j < len; j++) { - chr = ref[j]; - span = $.el('span', { - textContent: chr - }); - if (chr === ' ') { - span.className = 'space'; - } - if (chr === ']') { - nodes.push(spacer()); - } - nodes.push(span); - if (chr === '[') { - nodes.push(spacer()); - } - } - break; - case 'A': - a = node.cloneNode(true); - nodes.push(a); - } - } - return nodes; - } - }; - -}).call(this); - -(function() { - var Build, - slice = [].slice; - - Build = { - staticPath: '//s.4cdn.org/image/', - gifIcon: window.devicePixelRatio >= 2 ? '@2x.gif' : '.gif', - spoilerRange: $.dict(), - shortFilename: function(filename) { - var ext; - ext = filename.match(/\.?[^\.]*$/)[0]; - if (filename.length - ext.length > 30) { - return (filename.match(/(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[^]){0,25}/)[0]) + "(...)" + ext; - } else { - return filename; - } - }, - spoilerThumb: function(boardID) { - var spoilerRange; - if (spoilerRange = Build.spoilerRange[boardID]) { - return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; - } else { - return Build.staticPath + "spoiler.png"; - } - }, - sameThread: function(boardID, threadID) { - return g.VIEW === 'thread' && g.BOARD.ID === boardID && g.THREADID === +threadID; - }, - threadURL: function(boardID, threadID) { - if (boardID !== g.BOARD.ID) { - return "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/thread/" + threadID; - } else if (g.VIEW !== 'thread' || +threadID !== g.THREADID) { - return "/" + boardID + "/thread/" + threadID; - } else { - return ''; - } - }, - postURL: function(boardID, threadID, postID) { - return (Build.threadURL(boardID, threadID)) + "#p" + postID; - }, - parseJSON: function(data, arg) { - var boardID, key, o, siteID; - siteID = arg.siteID, boardID = arg.boardID; - o = { - ID: data.no, - postID: data.no, - threadID: data.resto || data.no, - boardID: boardID, - siteID: siteID, - isReply: !!data.resto, - isSticky: !!data.sticky, - isClosed: !!data.closed, - isArchived: !!data.archived, - fileDeleted: !!data.filedeleted, - filesDeleted: data.filedeleted ? [0] : [] - }; - o.info = { - subject: $.unescape(data.sub), - email: $.unescape(data.email), - name: $.unescape(data.name) || '', - tripcode: data.trip, - pass: data.since4pass != null ? "" + data.since4pass : void 0, - uniqueID: data.id, - flagCode: data.country, - flagCodeTroll: data.board_flag, - flag: $.unescape(data.country_name || data.flag_name), - dateUTC: data.time, - dateText: data.now, - commentHTML: { - innerHTML: data.com || '' - } - }; - if (data.capcode) { - o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { - return c.toUpperCase(); - }); - o.capcodeHighlight = /_highlight$/.test(data.capcode); - delete o.info.uniqueID; - } - o.files = []; - if (data.ext) { - o.file = SW.yotsuba.Build.parseJSONFile(data, { - siteID: siteID, - boardID: boardID - }); - o.files.push(o.file); - } - o.extra = $.dict(); - for (key in data) { - if (key[0] === 'x') { - o.extra[key] = data[key]; - } - } - return o; - }, - parseJSONFile: function(data, arg) { - var boardID, filename, o, site, siteID; - siteID = arg.siteID, boardID = arg.boardID; - site = g.sites[siteID]; - filename = site.software === 'yotsuba' && boardID === 'f' ? "" + (encodeURIComponent(data.filename)) + data.ext : "" + data.tim + data.ext; - o = { - name: ($.unescape(data.filename)) + data.ext, - url: site.urls.file({ - siteID: siteID, - boardID: boardID - }, filename), - height: data.h, - width: data.w, - MD5: data.md5, - size: $.bytesToString(data.fsize), - thumbURL: site.urls.thumb({ - siteID: siteID, - boardID: boardID - }, data.tim + "s.jpg"), - theight: data.tn_h, - twidth: data.tn_w, - isSpoiler: !!data.spoiler, - tag: data.tag, - hasDownscale: !!data.m_img - }; - if ((data.h != null) && !/\.pdf$/.test(o.url)) { - o.dimensions = o.width + "x" + o.height; - } - return o; - }, - parseComment: function(html) { - html = html.replace(//gi, '\n').replace(/\n\n]*>/g, ''); - return $.unescape(html); - }, - parseCommentDisplay: function(html) { - var html2; - if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { - while ((html2 = html.replace(/(?:(?!<\/?s>).)*<\/s>/g, '[spoiler]')) !== html) { - html = html2; - } - } - html = html.replace(/^Rolled [^<]*<\/b>/i, '').replace(/ " + ((!o.isReply || boardID === "f" || subject) ? "" + E(subject || "") + " " : "") + "" + ((email) ? "" : "") + "" + E(name) + "" + ((tripcode) ? " " + E(tripcode) + "" : "") + ((pass) ? " " : "") + ((capcode) ? " ## " + E(capcode) + "" : "") + ((email) ? "" : "") + ((boardID === "f" && !o.isReply || capcodeDescription) ? "" : " ") + ((capcodeDescription) ? " \""" : "") + ((uniqueID && !capcode) ? " (ID: " + E(uniqueID) + ")" : "") + ((flagCode) ? " " : "") + ((flagCodeTroll) ? " " : "") + " " + E(dateText) + " No." + E(ID) + "" + ((o.isSticky) ? " \"Sticky\"" : "") + ((o.isClosed && !o.isArchived) ? " \"Closed\"" : "") + ((o.isArchived) ? " \"Archived\"" : "") + ((!o.isReply && g.VIEW === "index") ? "   [Reply]" : "") + ""}; - - /* File Info */ - if (file) { - protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; - fileURL = file.url.replace(protocol, ''); - shortFilename = Build.shortFilename(file.name); - fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); - } - fileBlock = {innerHTML: ((file) ? "
" + ((boardID === "f") ? "
File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + ((file.tag) ? ", " + E(file.tag) : "") + ")
" : "
File: " + ((file.isSpoiler) ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
\""") + "
" : ((o.fileDeleted) ? "
\"File
" : ""))}; - - /* Whole Post */ - postClass = o.isReply ? 'reply' : 'op'; - wholePost = {innerHTML: ((o.isReply) ? "
>>
" : "") + "
" + ((o.isReply) ? (postInfo).innerHTML + (fileBlock).innerHTML : (fileBlock).innerHTML + (postInfo).innerHTML) + "
" + (commentHTML).innerHTML + "
"}; - container = $.el('div', { - className: "postContainer " + postClass + "Container", - id: "pc" + ID - }); - $.extend(container, wholePost); - ref1 = $$('.quotelink', container); - for (i = 0, len = ref1.length; i < len; i++) { - quote = ref1[i]; - href = quote.getAttribute('href'); - if (href[0] === '#') { - if (!Build.sameThread(boardID, threadID)) { - quote.href = Build.threadURL(boardID, threadID) + href; - } - } else { - if ((match = quote.href.match(SW.yotsuba.regexp.quotelink)) && (Build.sameThread(match[1], match[2]))) { - quote.href = href.match(/(#[^#]*)?$/)[0] || '#'; - } - } - } - return container; - }, - summaryText: function(status, posts, files) { - var text; - text = ''; - if (status) { - text += status + " "; - } - text += posts + " post" + (posts > 1 ? 's' : ''); - if (+files) { - text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); - } - return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; - }, - summary: function(boardID, threadID, posts, files) { - return $.el('a', { - className: 'summary', - textContent: Build.summaryText('', posts, files), - href: "/" + boardID + "/thread/" + threadID - }); - }, - thread: function(thread, data, withReplies) { - var files, posts, ref, root, summary; - if ((root = thread.nodes.root)) { - $.rmAll(root); - } else { - thread.nodes.root = root = $.el('div', { - className: 'thread', - id: "t" + data.no - }); - } - if (Build.hat) { - $.add(root, Build.hat.cloneNode(false)); - } - $.add(root, thread.OP.nodes.root); - if (data.omitted_posts || !withReplies && data.replies) { - ref = withReplies ? [ - data.omitted_posts, data.images - data.last_replies.filter(function(data) { - return !!data.ext; - }).length - ] : [data.replies, data.images], posts = ref[0], files = ref[1]; - summary = Build.summary(thread.board.ID, data.no, posts, files); - $.add(root, summary); - } - return root; - }, - catalogThread: function(thread, data, pageCount) { - var br, container, cssText, fileCount, gifIcon, i, imgClass, len, postCount, ratio, ref, root, spoilerRange, src, staticPath, tn_h, tn_w; - staticPath = Build.staticPath, gifIcon = Build.gifIcon; - tn_w = data.tn_w, tn_h = data.tn_h; - if (data.spoiler && !Conf['Reveal Spoiler Thumbnails']) { - src = staticPath + "spoiler"; - if (spoilerRange = Build.spoilerRange[thread.board]) { - src += ("-" + thread.board) + Math.floor(1 + spoilerRange * Math.random()); - } - src += '.png'; - imgClass = 'spoiler-file'; - cssText = "--tn-w: 100; --tn-h: 100;"; - } else if (data.filedeleted) { - src = staticPath + "filedeleted-res" + gifIcon; - imgClass = 'deleted-file'; - } else if (thread.OP.file) { - src = thread.OP.file.thumbURL; - ratio = 250 / Math.max(tn_w, tn_h); - cssText = "--tn-w: " + (tn_w * ratio) + "; --tn-h: " + (tn_h * ratio) + ";"; - } else { - src = staticPath + "nofile.png"; - imgClass = 'no-file'; - } - postCount = data.replies + 1; - fileCount = data.images + !!data.ext; - container = $.el('div', {innerHTML: "
" + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "" + ((thread.isSticky) ? "" : "") + ((thread.isClosed) ? "" : "") + "
"}); - $.before(thread.OP.nodes.info, slice.call(container.childNodes)); - ref = $$('br', thread.OP.nodes.comment); - for (i = 0, len = ref.length; i < len; i++) { - br = ref[i]; - if (br.previousSibling && br.previousSibling.nodeName === 'BR') { - $.addClass(br, 'extra-linebreak'); - } - } - root = $.el('div', { - className: 'thread catalog-thread', - id: "t" + thread - }); - if (thread.OP.highlights) { - $.addClass.apply($, [root].concat(slice.call(thread.OP.highlights))); - } - if (!thread.OP.file) { - $.addClass(root, 'noFile'); - } - root.style.cssText = cssText || ''; - return root; - }, - catalogReply: function(thread, data) { - var excerpt, link; - excerpt = ''; - if (data.com) { - excerpt = Build.parseCommentDisplay(data.com).replace(/>>\d+/g, '').trim().replace(/\n+/g, ' // '); - } - if (data.ext) { - excerpt || (excerpt = "" + ($.unescape(data.filename)) + data.ext); - } - if (data.com) { - excerpt || (excerpt = $.unescape(data.com.replace(//gi, ' // '))); - } - excerpt || (excerpt = '\xA0'); - if (excerpt.length > 73) { - excerpt = excerpt.slice(0, 70) + "..."; - } - link = Build.postURL(thread.board.ID, thread.ID, data.no); - return $.el('div', { - className: 'catalog-reply' - }, {innerHTML: ": " + E(excerpt) + "..."}); - } - }; - - SW.yotsuba.Build = Build; - -}).call(this); - -Site = (function() { - var Site; - - Site = { - defaultProperties: { - '4chan.org': { - software: 'yotsuba' - }, - '4channel.org': { - canonical: '4chan.org' - }, - '4cdn.org': { - canonical: '4chan.org' - }, - 'notso.smuglo.li': { - canonical: 'smuglo.li' - }, - 'smugloli.net': { - canonical: 'smuglo.li' - }, - 'smug.nepu.moe': { - canonical: 'smuglo.li' - } - }, - init: function(cb) { - var hostname; - $.extend(Conf['siteProperties'], Site.defaultProperties); - hostname = Site.resolve(); - if (hostname && $.hasOwn(SW, Conf['siteProperties'][hostname].software)) { - this.set(hostname); - cb(); - } - return $.onExists(doc, 'body', (function(_this) { - return function() { - var base, base1, changed, changes, key, properties, software; - for (software in SW) { - if (!((changes = typeof (base = SW[software]).detect === "function" ? base.detect() : void 0))) { - continue; - } - changes.software = software; - hostname = location.hostname.replace(/^www\./, ''); - properties = ((base1 = Conf['siteProperties'])[hostname] || (base1[hostname] = $.dict())); - changed = 0; - for (key in changes) { - if (!(properties[key] !== changes[key])) { - continue; - } - properties[key] = changes[key]; - changed++; - } - if (changed) { - $.set('siteProperties', Conf['siteProperties']); - } - if (!g.SITE) { - _this.set(hostname); - cb(); - } - return; - } - }; - })(this)); - }, - resolve: function(url) { - var canonical, hostname; - if (url == null) { - url = location; - } - hostname = url.hostname; - while (hostname && !$.hasOwn(Conf['siteProperties'], hostname)) { - hostname = hostname.replace(/^[^.]*\.?/, ''); - } - if (hostname) { - if ((canonical = Conf['siteProperties'][hostname].canonical)) { - hostname = canonical; - } - } - return hostname; - }, - parseURL: function(url) { - var siteID; - siteID = Site.resolve(url); - return Main.parseURL(g.sites[siteID], url); - }, - set: function(hostname) { - var ID, properties, ref, site, software; - ref = Conf['siteProperties']; - for (ID in ref) { - properties = ref[ID]; - if (properties.canonical) { - continue; - } - software = properties.software; - if (!(software && $.hasOwn(SW, software))) { - continue; - } - g.sites[ID] = site = Object.create(SW[software]); - $.extend(site, { - ID: ID, - siteID: ID, - properties: properties, - software: software - }); - } - return g.SITE = g.sites[hostname]; - } - }; - - return Site; - -}).call(this); - -Redirect = (function() { - var Redirect, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Redirect = { - archives: [ - { "uid": 3, "name": "4plebs", "domain": "archive.4plebs.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "adv", "f", "hr", "mlpol", "mo", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ], "files": [ "adv", "f", "hr", "mlpol", "mo", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ], "reports": true }, - { "uid": 10, "name": "warosu", "domain": "warosu.org", "http": false, "https": true, "software": "fuuka", "boards": [ "3", "biz", "cgl", "ck", "diy", "fa", "ic", "jp", "lit", "sci", "vr", "vt" ], "files": [ "3", "biz", "cgl", "ck", "diy", "fa", "ic", "jp", "lit", "sci", "vr", "vt" ], "search": [ "biz", "cgl", "ck", "diy", "fa", "ic", "jp", "lit", "sci", "vr", "vt" ] }, - { "uid": 23, "name": "Desuarchive", "domain": "desuarchive.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "a", "aco", "an", "c", "cgl", "co", "d", "fit", "g", "his", "int", "k", "m", "mlp", "mu", "q", "qa", "r9k", "tg", "trash", "vr", "wsg" ], "files": [ "a", "aco", "an", "c", "cgl", "co", "d", "fit", "g", "his", "int", "k", "m", "mlp", "mu", "q", "qa", "r9k", "tg", "trash", "vr" ], "reports": true }, - { "uid": 24, "name": "fireden.net", "domain": "boards.fireden.net", "http": false, "https": true, "software": "foolfuuka", "boards": [ "cm", "co", "ic", "sci", "vip", "y" ], "files": [ "cm", "co", "ic", "sci", "vip", "y" ], "search": [ "cm", "co", "ic", "sci", "y" ] }, - { "uid": 25, "name": "arch.b4k.co", "domain": "arch.b4k.co", "http": true, "https": true, "software": "foolfuuka", "boards": [ "g", "mlp", "qb", "v", "vg", "vm", "vmg", "vp", "vrpg", "vst" ], "files": [ "qb", "v", "vg", "vm", "vmg", "vp", "vrpg", "vst" ], "search": [ "qb", "v", "vg", "vm", "vmg", "vp", "vrpg", "vst" ] }, - { "uid": 29, "name": "Archived.Moe", "domain": "archived.moe", "http": true, "https": true, "software": "foolfuuka", "boards": [ "3", "a", "aco", "adv", "an", "asp", "b", "bant", "biz", "c", "can", "cgl", "ck", "cm", "co", "cock", "con", "d", "diy", "e", "f", "fa", "fap", "fit", "fitlit", "g", "gd", "gif", "h", "hc", "his", "hm", "hr", "i", "ic", "int", "jp", "k", "lgbt", "lit", "m", "mlp", "mlpol", "mo", "mtv", "mu", "n", "news", "o", "out", "outsoc", "p", "po", "pol", "pw", "q", "qa", "qb", "qst", "r", "r9k", "s", "s4s", "sci", "soc", "sp", "spa", "t", "tg", "toy", "trash", "trv", "tv", "u", "v", "vg", "vint", "vip", "vm", "vmg", "vp", "vr", "vrpg", "vst", "vt", "w", "wg", "wsg", "wsr", "x", "xs", "y" ], "files": [ "can", "cock", "con", "fap", "fitlit", "gd", "mlpol", "mo", "mtv", "outsoc", "po", "q", "qb", "qst", "spa", "vint", "vip" ], "search": [ "aco", "adv", "an", "asp", "b", "bant", "biz", "c", "can", "cgl", "ck", "cm", "cock", "con", "d", "diy", "e", "f", "fap", "fitlit", "gd", "gif", "h", "hc", "his", "hm", "hr", "i", "ic", "lgbt", "lit", "mlpol", "mo", "mtv", "n", "news", "o", "out", "outsoc", "p", "po", "pw", "q", "qa", "qst", "r", "s", "soc", "spa", "trv", "u", "vint", "vip", "vrpg", "w", "wg", "wsg", "wsr", "x", "y" ], "reports": true }, - { "uid": 30, "name": "TheBArchive.com", "domain": "thebarchive.com", "http": true, "https": true, "software": "foolfuuka", "boards": [ "b", "bant" ], "files": [ "b", "bant" ], "reports": true }, - { "uid": 31, "name": "Archive Of Sins", "domain": "archiveofsins.com", "http": true, "https": true, "software": "foolfuuka", "boards": [ "h", "hc", "hm", "i", "lgbt", "r", "s", "soc", "t", "u" ], "files": [ "h", "hc", "hm", "i", "lgbt", "r", "s", "soc", "t", "u" ], "reports": true }, - { "uid": 34, "name": "TokyoChronos", "domain": "www.tokyochronos.net", "http": false, "https": true, "software": "foolfuuka", "boards": [ "c", "g", "jp", "mu", "vp", "vrpg", "vt" ], "files": [], "reports": true }, - { "uid": 36, "name": "palanq.win", "domain": "archive.palanq.win", "http": false, "https": true, "software": "foolfuuka", "boards": [ "bant", "c", "con", "e", "i", "n", "news", "out", "p", "pw", "qst", "toy", "vip", "vp", "vt", "w", "wg", "wsr" ], "files": [ "bant", "c", "e", "i", "n", "news", "out", "p", "pw", "qst", "toy", "vip", "vp", "vt", "w", "wg", "wsr" ], "reports": true }, - { "uid": 37, "name": "Eientei", "domain": "eientei.xyz", "http": false, "https": true, "software": "Eientei", "boards": [ "3", "i", "sci", "xs" ], "files": [ "3", "i", "sci", "xs" ], "reports": true } - ], - init: function() { - var now, ref; - this.selectArchives(); - if (Conf['archiveAutoUpdate']) { - now = Date.now(); - if (!((now - 2 * $.DAY < (ref = Conf['lastarchivecheck']) && ref <= now))) { - return this.update(); - } - } - }, - selectArchives: function() { - var archive, archives, boardID, boards, data, files, id, j, k, key, l, len, len1, len2, name, o, record, ref, ref1, ref2, software, type, uid; - o = { - thread: $.dict(), - post: $.dict(), - file: $.dict() - }; - archives = $.dict(); - ref = Conf['archives']; - for (j = 0, len = ref.length; j < len; j++) { - data = ref[j]; - ref1 = ['boards', 'files']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - key = ref1[k]; - if (!(data[key] instanceof Array)) { - data[key] = []; - } - } - uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software; - if (software !== 'fuuka' && software !== 'foolfuuka') { - continue; - } - archives[JSON.stringify(uid != null ? uid : name)] = data; - for (l = 0, len2 = boards.length; l < len2; l++) { - boardID = boards[l]; - if (!(boardID in o.thread)) { - o.thread[boardID] = data; - } - if (!(boardID in o.post || software !== 'foolfuuka')) { - o.post[boardID] = data; - } - if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) { - o.file[boardID] = data; - } - } - } - ref2 = Conf['selectedArchives']; - for (boardID in ref2) { - record = ref2[boardID]; - for (type in record) { - id = record[type]; - if (!((archive = archives[JSON.stringify(id)]) && $.hasOwn(o, type))) { - continue; - } - boards = type === 'file' ? archive.files : archive.boards; - if (indexOf.call(boards, boardID) >= 0) { - o[type][boardID] = archive; - } - } - } - return Redirect.data = o; - }, - update: function(cb) { - var err, fail, i, j, k, len, len1, load, nloaded, ref, ref1, response, responses, url, urls; - urls = []; - responses = []; - nloaded = 0; - ref = Conf['archiveLists'].split('\n'); - for (j = 0, len = ref.length; j < len; j++) { - url = ref[j]; - if (!(url[0] !== '#')) { - continue; - } - url = url.trim(); - if (url) { - urls.push(url); - } - } - fail = function(url, action, msg) { - return new Notice('warning', "Error " + action + " archive data from\n" + url + "\n" + msg, 20); - }; - load = function(i) { - return function() { - var response; - if (this.status !== 200) { - return fail(urls[i], 'fetching', (this.status ? "Error " + this.statusText + " (" + this.status + ")" : 'Connection Error')); - } - response = this.response; - if (!(response instanceof Array)) { - response = [response]; - } - responses[i] = response; - nloaded++; - if (nloaded === urls.length) { - return Redirect.parse(responses, cb); - } - }; - }; - if (urls.length) { - for (i = k = 0, len1 = urls.length; k < len1; i = ++k) { - url = urls[i]; - if ((ref1 = url[0]) === '[' || ref1 === '{') { - try { - response = JSON.parse(url); - } catch (error) { - err = error; - fail(url, 'parsing', err.message); - continue; - } - load(i).call({ - status: 200, - response: response - }); - } else { - CrossOrigin.ajax(url, { - onloadend: load(i) - }); - } - } - } else { - Redirect.parse([], cb); - } - }, - parse: function(responses, cb) { - var archiveUIDs, archives, data, items, j, k, len, len1, ref, response, uid; - archives = []; - archiveUIDs = $.dict(); - for (j = 0, len = responses.length; j < len; j++) { - response = responses[j]; - for (k = 0, len1 = response.length; k < len1; k++) { - data = response[k]; - uid = JSON.stringify((ref = data.uid) != null ? ref : data.name); - if (uid in archiveUIDs) { - $.extend(archiveUIDs[uid], data); - } else { - archiveUIDs[uid] = $.dict.clone(data); - archives.push(data); - } - } - } - items = { - archives: archives, - lastarchivecheck: Date.now() - }; - $.set(items); - $.extend(Conf, items); - Redirect.selectArchives(); - return typeof cb === "function" ? cb() : void 0; - }, - to: function(dest, data) { - var archive; - archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; - if (!archive) { - return ''; - } - return Redirect[dest](archive, data); - }, - protocol: function(archive) { - var protocol; - protocol = location.protocol; - if (!$.getOwn(archive, protocol.slice(0, -1))) { - protocol = protocol === 'https:' ? 'http:' : 'https:'; - } - return protocol + "//"; - }, - thread: function(archive, arg) { - var boardID, path, postID, threadID; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID; - path = threadID ? boardID + "/thread/" + threadID : boardID + "/post/" + postID; - if (archive.software === 'foolfuuka') { - path += '/'; - } - if (threadID && postID) { - path += archive.software === 'foolfuuka' ? "#" + postID : "#p" + postID; - } - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; - }, - post: function(archive, arg) { - var boardID, postID, protocol, url; - boardID = arg.boardID, postID = arg.postID; - protocol = Redirect.protocol(archive); - url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; - if (!Redirect.securityCheck(url)) { - return ''; - } - return url; - }, - file: function(archive, arg) { - var boardID, filename; - boardID = arg.boardID, filename = arg.filename; - if (!filename) { - return ''; - } - if (boardID === 'f') { - filename = encodeURIComponent($.unescape(decodeURIComponent(filename))); - } else { - if (/[sm]\.jpg$/.test(filename)) { - return ''; - } - } - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/full_image/" + filename; - }, - board: function(archive, arg) { - var boardID; - boardID = arg.boardID; - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/"; - }, - search: function(archive, arg) { - var boardID, path, type, value; - boardID = arg.boardID, type = arg.type, value = arg.value; - type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type; - if (type === 'capcode') { - value = $.getOwn({ - 'Developer': 'dev', - 'Verified': 'ver' - }, value) || value.toLowerCase(); - } else if (type === 'image') { - value = value.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }); - } - value = encodeURIComponent(value); - path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; - }, - report: function(boardID) { - var archive, boards, domain, https, j, len, name, ref, reports, software, urls; - urls = []; - ref = Conf['archives']; - for (j = 0, len = ref.length; j < len; j++) { - archive = ref[j]; - software = archive.software, https = archive.https, reports = archive.reports, boards = archive.boards, name = archive.name, domain = archive.domain; - if (software === 'foolfuuka' && https && reports && boards instanceof Array && indexOf.call(boards, boardID) >= 0) { - urls.push([name, "https://" + domain + "/_/api/chan/offsite_report/"]); - } - } - return urls; - }, - securityCheck: function(url) { - return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; - }, - navigate: function(dest, data, alternative) { - var url; - if (!Redirect.data) { - Redirect.init(); - } - url = Redirect.to(dest, data); - if (url && (Redirect.securityCheck(url) || confirm("Redirect to " + url + "?\n\nYour connection will not be encrypted."))) { - return location.replace(url); - } else if (alternative) { - return location.replace(alternative); - } - } - }; - - return Redirect; - -}).call(this); - -Anonymize = (function() { - var Anonymize; - - Anonymize = { - init: function() { - if (!Conf['Anonymize']) { - return; - } - return $.addClass(doc, 'anonymize'); - } - }; - - return Anonymize; - -}).call(this); - -Filter = (function() { - var Filter, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - Filter = { - filters: $.dict(), - init: function() { - var base, base1, boards, err, excludes, file, filter, hide, hl, i, isstring, j, key, len, len1, line, mask, noti, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, regexp, stub, top, type, types; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'catalog') && Conf['Filter'])) { - return; - } - if (g.VIEW === 'catalog' && !Conf['Filter in Native Catalog']) { - return; - } - if (!Conf['Filtered Backlinks']) { - $.addClass(doc, 'hide-backlinks'); - } - for (key in Config.filter) { - ref1 = Conf[key].split('\n'); - for (i = 0, len = ref1.length; i < len; i++) { - line = ref1[i]; - if (line[0] === '#') { - continue; - } - if (!(regexp = line.match(/\/(.*)\/(\w*)/))) { - continue; - } - filter = line.replace(regexp[0], ''); - boards = this.parseBoards((ref2 = filter.match(/(?:^|;)\s*boards:([^;]+)/)) != null ? ref2[1] : void 0); - excludes = this.parseBoards((ref3 = filter.match(/(?:^|;)\s*exclude:([^;]+)/)) != null ? ref3[1] : void 0); - if ((isstring = (key === 'uniqueID' || key === 'MD5'))) { - regexp = regexp[1]; - } else { - try { - regexp = RegExp(regexp[1], regexp[2]); - } catch (error) { - err = error; - new Notice('warning', [$.tn("Invalid " + key + " filter:"), $.el('br'), $.tn(line), $.el('br'), $.tn(err.message)], 60); - continue; - } - } - op = ((ref4 = filter.match(/(?:^|;)\s*op:(no|only)/)) != null ? ref4[1] : void 0) || ''; - mask = $.getOwn({ - 'no': 1, - 'only': 2 - }, op) || 0; - file = ((ref5 = filter.match(/(?:^|;)\s*file:(no|only)/)) != null ? ref5[1] : void 0) || ''; - mask = mask | ($.getOwn({ - 'no': 4, - 'only': 8 - }, file) || 0); - stub = (function() { - var ref6; - switch ((ref6 = filter.match(/(?:^|;)\s*stub:(yes|no)/)) != null ? ref6[1] : void 0) { - case 'yes': - return true; - case 'no': - return false; - default: - return Conf['Stubs']; - } - })(); - noti = /(?:^|;)\s*notify/.test(filter); - if ((hl = /(?:^|;)\s*highlight/.test(filter))) { - hl = ((ref6 = filter.match(/(?:^|;)\s*highlight:([\w-]+)/)) != null ? ref6[1] : void 0) || 'filter-highlight'; - top = ((ref7 = filter.match(/(?:^|;)\s*top:(yes|no)/)) != null ? ref7[1] : void 0) || 'yes'; - top = top === 'yes'; - } - if (key === 'general') { - if ((types = filter.match(/(?:^|;)\s*type:([^;]*)/))) { - types = types[1].split(','); - } else { - types = ['subject', 'name', 'filename', 'comment']; - } - } - hide = !(hl || noti); - filter = { - isstring: isstring, - regexp: regexp, - boards: boards, - excludes: excludes, - mask: mask, - hide: hide, - stub: stub, - hl: hl, - top: top, - noti: noti - }; - if (key === 'general') { - for (j = 0, len1 = types.length; j < len1; j++) { - type = types[j]; - ((base = this.filters)[type] || (base[type] = [])).push(filter); - } - } else { - ((base1 = this.filters)[key] || (base1[key] = [])).push(filter); - } - } - } - if (!Object.keys(this.filters).length) { - return; - } - if (g.VIEW === 'catalog') { - return Filter.catalog(); - } else { - return Callbacks.Post.push({ - name: 'Filter', - cb: this.node - }); - } - }, - parseBoards: function(boardsRaw) { - var boardID, boardID2, boards, i, j, len, len1, ref, ref1, ref2, ref3, site, siteFilter, siteID; - if (!boardsRaw) { - return false; - } - if ((boards = Filter.parseBoardsMemo[boardsRaw])) { - return boards; - } - boards = $.dict(); - siteFilter = ''; - ref = boardsRaw.split(','); - for (i = 0, len = ref.length; i < len; i++) { - boardID = ref[i]; - if (indexOf.call(boardID, ':') >= 0) { - ref1 = boardID.split(':').slice(-2), siteFilter = ref1[0], boardID = ref1[1]; - } - ref2 = g.sites; - for (siteID in ref2) { - site = ref2[siteID]; - if (siteID.slice(0, siteFilter.length) === siteFilter) { - if (boardID === 'nsfw' || boardID === 'sfw') { - ref3 = (typeof site.sfwBoards === "function" ? site.sfwBoards(boardID === 'sfw') : void 0) || []; - for (j = 0, len1 = ref3.length; j < len1; j++) { - boardID2 = ref3[j]; - boards[siteID + "/" + boardID2] = true; - } - } else { - boards[siteID + "/" + (encodeURIComponent(boardID))] = true; - } - } - } - } - Filter.parseBoardsMemo[boardsRaw] = boards; - return boards; - }, - parseBoardsMemo: $.dict(), - test: function(post, hideable) { - var board, filter, hide, hl, i, j, key, len, len1, mask, noti, ref, ref1, ref2, site, stub, top, value; - if (hideable == null) { - hideable = true; - } - if (post.filterResults) { - return post.filterResults; - } - hide = false; - stub = true; - hl = void 0; - top = false; - noti = false; - if (QuoteYou.isYou(post)) { - hideable = false; - } - mask = (post.isReply ? 2 : 1); - mask = mask | (post.file ? 4 : 8); - board = post.siteID + "/" + post.boardID; - site = post.siteID + "/*"; - for (key in Filter.filters) { - ref = Filter.values(key, post); - for (i = 0, len = ref.length; i < len; i++) { - value = ref[i]; - ref1 = Filter.filters[key]; - for (j = 0, len1 = ref1.length; j < len1; j++) { - filter = ref1[j]; - if ((filter.boards && !(filter.boards[board] || filter.boards[site])) || (filter.excludes && (filter.excludes[board] || filter.excludes[site])) || (filter.mask & mask) || (filter.isstring ? filter.regexp !== value : !filter.regexp.test(value))) { - continue; - } - if (filter.hide) { - if (hideable) { - hide = true; - stub && (stub = filter.stub); - } - } else { - if (!(hl && (ref2 = filter.hl, indexOf.call(hl, ref2) >= 0))) { - (hl || (hl = [])).push(filter.hl); - } - top || (top = filter.top); - if (filter.noti) { - noti = true; - } - } - } - } - } - if (hide) { - return { - hide: hide, - stub: stub - }; - } else { - return { - hl: hl, - top: top, - noti: noti - }; - } - }, - node: function() { - var hide, hl, noti, ref, stub, top; - if (this.isClone) { - return; - } - ref = Filter.test(this, !this.isFetchedQuote && (this.isReply || g.VIEW === 'index')), hide = ref.hide, stub = ref.stub, hl = ref.hl, top = ref.top, noti = ref.noti; - if (hide) { - if (this.isReply) { - PostHiding.hide(this, stub); - } else { - ThreadHiding.hide(this.thread, stub); - } - } else { - if (hl) { - this.highlights = hl; - $.addClass.apply($, [this.nodes.root].concat(slice.call(hl))); - } - } - if (noti && Unread.posts && (this.ID > Unread.lastReadPost) && !QuoteYou.isYou(this)) { - return Unread.openNotification(this, ' triggered a notification filter'); - } - }, - catalog: function() { - var base, url; - if (!(url = typeof (base = g.SITE.urls).catalogJSON === "function" ? base.catalogJSON(g.BOARD) : void 0)) { - return; - } - Filter.catalogData = $.dict(); - $.ajax(url, { - onloadend: Filter.catalogParse - }); - return Callbacks.CatalogThreadNative.push({ - name: 'Filter', - cb: this.catalogNode - }); - }, - catalogParse: function() { - var i, item, j, len, len1, page, ref, ref1, ref2; - if ((ref = this.status) !== 200 && ref !== 404) { - new Notice('warning', "Failed to fetch catalog JSON data. " + (this.status ? "Error " + this.statusText + " (" + this.status + ")" : 'Connection Error'), 1); - return; - } - ref1 = this.response; - for (i = 0, len = ref1.length; i < len; i++) { - page = ref1[i]; - ref2 = page.threads; - for (j = 0, len1 = ref2.length; j < len1; j++) { - item = ref2[j]; - Filter.catalogData[item.no] = item; - } - } - g.BOARD.threads.forEach(function(thread) { - if (thread.catalogViewNative) { - return Filter.catalogNode.call(thread.catalogViewNative); - } - }); - }, - catalogNode: function() { - var base, hide, hl, ref, ref1, top; - if (!(this.boardID === g.BOARD.ID && Filter.catalogData[this.ID])) { - return; - } - if ((ref = QuoteYou.db) != null ? ref.get({ - siteID: g.SITE.ID, - boardID: this.boardID, - threadID: this.ID, - postID: this.ID - }) : void 0) { - return; - } - ref1 = Filter.test(g.SITE.Build.parseJSON(Filter.catalogData[this.ID], this)), hide = ref1.hide, hl = ref1.hl, top = ref1.top; - if (hide) { - return this.nodes.root.hidden = true; - } else { - if (hl) { - this.highlights = hl; - $.addClass.apply($, [this.nodes.root].concat(slice.call(hl))); - } - if (top) { - $.prepend(this.nodes.root.parentNode, this.nodes.root); - return typeof (base = g.SITE).catalogPin === "function" ? base.catalogPin(this.nodes.root) : void 0; - } - } - }, - isHidden: function(post) { - return !!Filter.test(post).hide; - }, - valueF: { - postID: function(post) { - return ["" + post.ID]; - }, - name: function(post) { - return [post.info.name]; - }, - uniqueID: function(post) { - return [post.info.uniqueID || '']; - }, - tripcode: function(post) { - return [post.info.tripcode]; - }, - capcode: function(post) { - return [post.info.capcode]; - }, - pass: function(post) { - return [post.info.pass]; - }, - email: function(post) { - return [post.info.email]; - }, - subject: function(post) { - return [post.info.subject || (post.isReply ? void 0 : '')]; - }, - comment: function(post) { - var base, ref, ref1; - return [((base = post.info).comment != null ? base.comment : base.comment = (ref = g.sites[post.siteID]) != null ? (ref1 = ref.Build) != null ? typeof ref1.parseComment === "function" ? ref1.parseComment(post.info.commentHTML.innerHTML) : void 0 : void 0 : void 0)]; - }, - flag: function(post) { - return [post.info.flag]; - }, - filename: function(post) { - return post.files.map(function(f) { - return f.name; - }); - }, - dimensions: function(post) { - return post.files.map(function(f) { - return f.dimensions; - }); - }, - filesize: function(post) { - return post.files.map(function(f) { - return f.size; - }); - }, - MD5: function(post) { - return post.files.map(function(f) { - return f.MD5; - }); - } - }, - values: function(key, post) { - if ($.hasOwn(Filter.valueF, key)) { - return Filter.valueF[key](post).filter(function(v) { - return v != null; - }); - } else { - return [ - key.split('+').map(function(k) { - var f; - if ((f = $.getOwn(Filter.valueF, k))) { - return f(post).map(function(v) { - return v || ''; - }).join('\n'); - } else { - return ''; - } - }).join('\n') - ]; - } - }, - addFilter: function(type, re, cb) { - if (!$.hasOwn(Config.filter, type)) { - return; - } - return $.get(type, Conf[type], function(item) { - var save; - save = item[type]; - save = save ? save + "\n" + re : re; - return $.set(type, save, cb); - }); - }, - removeFilters: function(type, res, cb) { - return $.get(type, Conf[type], function(item) { - var save; - save = item[type]; - res = res.map(Filter.escape).join('|'); - save = save.replace(RegExp("(?:$\n|^)(?:" + res + ")$", 'mg'), ''); - return $.set(type, save, cb); - }); - }, - showFilters: function(type) { - var section, select; - Settings.open('Filter'); - section = $('.section-container'); - select = $('select[name=filter]', section); - select.value = type; - Settings.selectFilter.call(select); - return $.onExists(section, 'textarea', function(ta) { - var tl; - tl = ta.textLength; - ta.setSelectionRange(tl, tl); - return ta.focus(); - }); - }, - quickFilterMD5: function() { - var files, filter, links, msg, notice, origin, post; - post = Get.postFromNode(this); - files = post.files.filter(function(f) { - return f.MD5; - }); - if (!files.length) { - return; - } - filter = files.map(function(f) { - return "/" + f.MD5 + "/"; - }).join('\n'); - Filter.addFilter('MD5', filter); - origin = post.origin || post; - if (origin.isReply) { - PostHiding.hide(origin); - } else if (g.VIEW === 'index') { - ThreadHiding.hide(origin.thread); - } - if (!Conf['MD5 Quick Filter Notifications']) { - if (post.nodes.post.getBoundingClientRect().height) { - new Notice('info', 'MD5 filtered.', 2); - } - return; - } - notice = Filter.quickFilterMD5.notice; - if (notice) { - notice.filters.push(filter); - notice.posts.push(origin); - return $('span', notice.el).textContent = notice.filters.length + " MD5s filtered."; - } else { - msg = $.el('div', {innerHTML: "MD5 filtered. [show] [undo]"}); - notice = Filter.quickFilterMD5.notice = new Notice('info', msg, void 0, function() { - return delete Filter.quickFilterMD5.notice; - }); - notice.filters = [filter]; - notice.posts = [origin]; - links = $$('a', msg); - $.on(links[0], 'click', Filter.quickFilterCB.show.bind(notice)); - return $.on(links[1], 'click', Filter.quickFilterCB.undo.bind(notice)); - } - }, - quickFilterCB: { - show: function() { - Filter.showFilters('MD5'); - return this.close(); - }, - undo: function() { - var i, len, post, ref; - Filter.removeFilters('MD5', this.filters); - ref = this.posts; - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - if (post.isReply) { - PostHiding.show(post); - } else if (g.VIEW === 'index') { - ThreadHiding.show(post.thread); - } - } - return this.close(); - } - }, - escape: function(value) { - return value.replace(/\/|\\|\^|\$|\n|\.|\(|\)|\{|\}|\[|\]|\?|\*|\+|\|/g, function(c) { - if (c === '\n') { - return '\\n'; - } else if (c === '\\') { - return '\\\\'; - } else { - return "\\" + c; - } - }); - }, - menu: { - init: function() { - var div, entry, i, len, ref, ref1, type; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Filter'])) { - return; - } - div = $.el('div', { - textContent: 'Filter' - }); - entry = { - el: div, - order: 50, - open: function(post) { - Filter.menu.post = post; - return true; - }, - subEntries: [] - }; - ref1 = [['Name', 'name'], ['Unique ID', 'uniqueID'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Pass Date', 'pass'], ['Email', 'email'], ['Subject', 'subject'], ['Comment', 'comment'], ['Flag', 'flag'], ['Filename', 'filename'], ['Image dimensions', 'dimensions'], ['Filesize', 'filesize'], ['Image MD5', 'MD5']]; - for (i = 0, len = ref1.length; i < len; i++) { - type = ref1[i]; - entry.subEntries.push(Filter.menu.createSubEntry(type[0], type[1])); - } - return Menu.menu.addEntry(entry); - }, - createSubEntry: function(text, type) { - var el; - el = $.el('a', { - href: 'javascript:;', - textContent: text - }); - el.dataset.type = type; - $.on(el, 'click', Filter.menu.makeFilter); - return { - el: el, - open: function(post) { - return Filter.values(type, post).length; - } - }; - }, - makeFilter: function() { - var res, type, values; - type = this.dataset.type; - values = Filter.values(type, Filter.menu.post); - res = values.map(function(value) { - var re; - re = type === 'uniqueID' || type === 'MD5' ? value : Filter.escape(value); - if (type === 'uniqueID' || type === 'MD5') { - return "/" + re + "/"; - } else { - return "/^" + re + "$/"; - } - }).join('\n'); - return Filter.addFilter(type, res, function() { - return Filter.showFilters(type); - }); - } - } - }; - - return Filter; - -}).call(this); - -PostHiding = (function() { - var PostHiding; - - PostHiding = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Reply Hiding Buttons'] && !(Conf['Menu'] && Conf['Reply Hiding Link'])) { - return; - } - if (Conf['Reply Hiding Buttons']) { - $.addClass(doc, "reply-hide"); - } - this.db = new DataBoard('hiddenPosts'); - return Callbacks.Post.push({ - name: 'Reply Hiding', - cb: this.node - }); - }, - isHidden: function(boardID, threadID, postID) { - return !!(PostHiding.db && PostHiding.db.get({ - boardID: boardID, - threadID: threadID, - postID: postID - })); - }, - node: function() { - var button, data, sa, sideArrows; - if (!this.isReply || this.isClone || this.isFetchedQuote) { - return; - } - if (data = PostHiding.db.get({ - boardID: this.board.ID, - threadID: this.thread.ID, - postID: this.ID - })) { - if (data.thisPost) { - PostHiding.hide(this, data.makeStub, data.hideRecursively); - } else { - Recursive.apply(PostHiding.hide, this, data.makeStub, true); - Recursive.add(PostHiding.hide, this, data.makeStub, true); - } - } - if (!Conf['Reply Hiding Buttons']) { - return; - } - button = PostHiding.makeButton(this, 'hide'); - if ((sa = g.SITE.selectors.sideArrows)) { - sideArrows = $(sa, this.nodes.root); - $.replace(sideArrows.firstChild, button); - return sideArrows.className = 'replacedSideArrows'; - } else { - return $.prepend(this.nodes.info, button); - } - }, - menu: { - init: function() { - var apply, div, hideStubLink, makeStub, ref, replies, thisPost; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { - return; - } - div = $.el('div', { - className: 'hide-reply-link', - textContent: 'Hide' - }); - apply = $.el('a', { - textContent: 'Apply', - href: 'javascript:;' - }); - $.on(apply, 'click', PostHiding.menu.hide); - thisPost = UI.checkbox('thisPost', 'This post', true); - replies = UI.checkbox('replies', 'Hide replies', Conf['Recursive Hiding']); - makeStub = UI.checkbox('makeStub', 'Make stub', Conf['Stubs']); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(post) { - if (!post.isReply || post.isClone || post.isHidden) { - return false; - } - PostHiding.menu.post = post; - return true; - }, - subEntries: [ - { - el: apply - }, { - el: thisPost - }, { - el: replies - }, { - el: makeStub - } - ] - }); - div = $.el('div', { - className: 'show-reply-link', - textContent: 'Show' - }); - apply = $.el('a', { - textContent: 'Apply', - href: 'javascript:;' - }); - $.on(apply, 'click', PostHiding.menu.show); - thisPost = UI.checkbox('thisPost', 'This post', false); - replies = UI.checkbox('replies', 'Show replies', false); - hideStubLink = $.el('a', { - textContent: 'Hide stub', - href: 'javascript:;' - }); - $.on(hideStubLink, 'click', PostHiding.menu.hideStub); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(post) { - var data; - if (!post.isReply || post.isClone || !post.isHidden) { - return false; - } - if (!(data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - }))) { - return false; - } - PostHiding.menu.post = post; - thisPost.firstChild.checked = post.isHidden; - replies.firstChild.checked = (data != null ? data.hideRecursively : void 0) != null ? data.hideRecursively : Conf['Recursive Hiding']; - return true; - }, - subEntries: [ - { - el: apply - }, { - el: thisPost - }, { - el: replies - } - ] - }); - return Menu.menu.addEntry({ - el: hideStubLink, - order: 15, - open: function(post) { - var data; - if (!post.isReply || post.isClone || !post.isHidden) { - return false; - } - if (!(data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - }))) { - return false; - } - return PostHiding.menu.post = post; - } - }); - }, - hide: function() { - var makeStub, parent, post, replies, thisPost; - parent = this.parentNode; - thisPost = $('input[name=thisPost]', parent).checked; - replies = $('input[name=replies]', parent).checked; - makeStub = $('input[name=makeStub]', parent).checked; - post = PostHiding.menu.post; - if (thisPost) { - PostHiding.hide(post, makeStub, replies); - } else if (replies) { - Recursive.apply(PostHiding.hide, post, makeStub, true); - Recursive.add(PostHiding.hide, post, makeStub, true); - } else { - return; - } - PostHiding.saveHiddenState(post, true, thisPost, makeStub, replies); - return $.event('CloseMenu'); - }, - show: function() { - var data, parent, post, replies, thisPost; - parent = this.parentNode; - thisPost = $('input[name=thisPost]', parent).checked; - replies = $('input[name=replies]', parent).checked; - post = PostHiding.menu.post; - if (thisPost) { - PostHiding.show(post, replies); - } else if (replies) { - Recursive.apply(PostHiding.show, post, true); - Recursive.rm(PostHiding.hide, post, true); - } else { - return; - } - if (data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - })) { - PostHiding.saveHiddenState(post, !(thisPost && replies), !thisPost, data.makeStub, !replies); - } - return $.event('CloseMenu'); - }, - hideStub: function() { - var data, post; - post = PostHiding.menu.post; - if (data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - })) { - PostHiding.show(post, data.hideRecursively); - PostHiding.hide(post, false, data.hideRecursively); - PostHiding.saveHiddenState(post, true, true, false, data.hideRecursively); - } - $.event('CloseMenu'); - } - }, - makeButton: function(post, type) { - var a, span; - span = $.el('span', { - className: "fa fa-" + (type === 'hide' ? 'minus' : 'plus') + "-square-o", - textContent: "" - }); - a = $.el('a', { - className: type + "-reply-button", - href: 'javascript:;' - }); - $.add(a, span); - $.on(a, 'click', PostHiding.toggle); - return a; - }, - saveHiddenState: function(post, isHiding, thisPost, makeStub, hideRecursively) { - var data; - data = { - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - }; - if (isHiding) { - data.val = { - thisPost: thisPost !== false, - makeStub: makeStub, - hideRecursively: hideRecursively - }; - return PostHiding.db.set(data); - } else { - return PostHiding.db["delete"](data); - } - }, - toggle: function() { - var post; - post = Get.postFromNode(this); - PostHiding[(post.isHidden ? 'show' : 'hide')](post); - return PostHiding.saveHiddenState(post, post.isHidden); - }, - hide: function(post, makeStub, hideRecursively) { - var a, i, len, quotelink, ref; - if (makeStub == null) { - makeStub = Conf['Stubs']; - } - if (hideRecursively == null) { - hideRecursively = Conf['Recursive Hiding']; - } - if (post.isHidden) { - return; - } - post.isHidden = true; - if (hideRecursively) { - Recursive.apply(PostHiding.hide, post, makeStub, true); - Recursive.add(PostHiding.hide, post, makeStub, true); - } - ref = Get.allQuotelinksLinkingTo(post); - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - $.addClass(quotelink, 'filtered'); - } - if (!makeStub) { - post.nodes.root.hidden = true; - return; - } - a = PostHiding.makeButton(post, 'show'); - $.add(a, $.tn(" " + post.info.nameBlock)); - post.nodes.stub = $.el('div', { - className: 'stub' - }); - $.add(post.nodes.stub, a); - if (Conf['Menu']) { - $.add(post.nodes.stub, Menu.makeButton(post)); - } - return $.prepend(post.nodes.root, post.nodes.stub); - }, - show: function(post, showRecursively) { - var i, len, quotelink, ref; - if (showRecursively == null) { - showRecursively = Conf['Recursive Hiding']; - } - if (post.nodes.stub) { - $.rm(post.nodes.stub); - delete post.nodes.stub; - } else { - post.nodes.root.hidden = false; - } - post.isHidden = false; - if (showRecursively) { - Recursive.apply(PostHiding.show, post, true); - Recursive.rm(PostHiding.hide, post); - } - ref = Get.allQuotelinksLinkingTo(post); - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - $.rmClass(quotelink, 'filtered'); - } - } - }; - - return PostHiding; - -}).call(this); - -Recursive = (function() { - var Recursive, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Recursive = { - recursives: $.dict(), - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - return Callbacks.Post.push({ - name: 'Recursive', - cb: this.node - }); - }, - node: function() { - var i, j, k, len, len1, obj, quote, recursive, ref, ref1; - if (this.isClone || this.isFetchedQuote) { - return; - } - ref = this.quotes; - for (j = 0, len = ref.length; j < len; j++) { - quote = ref[j]; - if (obj = Recursive.recursives[quote]) { - ref1 = obj.recursives; - for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { - recursive = ref1[i]; - recursive.apply(null, [this].concat(slice.call(obj.args[i]))); - } - } - } - }, - add: function() { - var args, base, name, obj, post, recursive; - recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - obj = (base = Recursive.recursives)[name = post.fullID] || (base[name] = { - recursives: [], - args: [] - }); - obj.recursives.push(recursive); - return obj.args.push(args); - }, - rm: function(recursive, post) { - var i, j, len, obj, rec, ref; - if (!(obj = Recursive.recursives[post.fullID])) { - return; - } - ref = obj.recursives; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - rec = ref[i]; - if (!(rec === recursive)) { - continue; - } - obj.recursives.splice(i, 1); - obj.args.splice(i, 1); - } - }, - apply: function() { - var args, fullID, post, recursive; - recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - fullID = post.fullID; - return g.posts.forEach(function(post) { - if (indexOf.call(post.quotes, fullID) >= 0) { - return recursive.apply(null, [post].concat(slice.call(args))); - } - }); - } - }; - - return Recursive; - -}).call(this); - -ThreadHiding = (function() { - var ThreadHiding; - - ThreadHiding = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'catalog') || !Conf['Thread Hiding Buttons'] && !(Conf['Menu'] && Conf['Thread Hiding Link']) && !Conf['JSON Index']) { - return; - } - this.db = new DataBoard('hiddenThreads'); - if (g.VIEW === 'catalog') { - return this.catalogWatch(); - } - this.catalogSet(g.BOARD); - $.on(d, 'IndexRefreshInternal', this.onIndexRefresh); - if (Conf['Thread Hiding Buttons']) { - $.addClass(doc, 'thread-hide'); - } - return Callbacks.Post.push({ - name: 'Thread Hiding', - cb: this.node - }); - }, - catalogSet: function(board) { - var hiddenThreads, threadID; - if (!($.hasStorage && g.SITE.software === 'yotsuba')) { - return; - } - hiddenThreads = ThreadHiding.db.get({ - boardID: board.ID, - defaultValue: $.dict() - }); - for (threadID in hiddenThreads) { - hiddenThreads[threadID] = true; - } - return localStorage.setItem("4chan-hide-t-" + board, JSON.stringify(hiddenThreads)); - }, - catalogWatch: function() { - if (!($.hasStorage && g.SITE.software === 'yotsuba')) { - return; - } - this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - return Main.ready(function() { - return new MutationObserver(ThreadHiding.catalogSave).observe($.id('threads'), { - attributes: true, - subtree: true, - attributeFilter: ['style'] - }); - }); - }, - catalogSave: function() { - var hiddenThreads2, threadID; - hiddenThreads2 = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - for (threadID in hiddenThreads2) { - if (!$.hasOwn(ThreadHiding.hiddenThreads, threadID)) { - ThreadHiding.db.set({ - boardID: g.BOARD.ID, - threadID: threadID, - val: { - makeStub: Conf['Stubs'] - } - }); - } - } - for (threadID in ThreadHiding.hiddenThreads) { - if (!$.hasOwn(hiddenThreads2, threadID)) { - ThreadHiding.db["delete"]({ - boardID: g.BOARD.ID, - threadID: threadID - }); - } - } - return ThreadHiding.hiddenThreads = hiddenThreads2; - }, - isHidden: function(boardID, threadID) { - return !!(ThreadHiding.db && ThreadHiding.db.get({ - boardID: boardID, - threadID: threadID - })); - }, - node: function() { - var data; - if (this.isReply || this.isClone || this.isFetchedQuote) { - return; - } - if (Conf['Thread Hiding Buttons']) { - $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); - } - if (data = ThreadHiding.db.get({ - boardID: this.board.ID, - threadID: this.ID - })) { - return ThreadHiding.hide(this.thread, data.makeStub); - } - }, - onIndexRefresh: function() { - return g.BOARD.threads.forEach(function(thread) { - var root; - root = thread.nodes.root; - if (thread.isHidden && thread.stub && !root.contains(thread.stub)) { - return ThreadHiding.makeStub(thread, root); - } - }); - }, - menu: { - init: function() { - var apply, div, hideStubLink, makeStub; - if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) { - return; - } - div = $.el('div', { - className: 'hide-thread-link', - textContent: 'Hide' - }); - apply = $.el('a', { - textContent: 'Apply', - href: 'javascript:;' - }); - $.on(apply, 'click', ThreadHiding.menu.hide); - makeStub = UI.checkbox('Stubs', 'Make stub'); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(arg) { - var isReply, thread; - thread = arg.thread, isReply = arg.isReply; - if (isReply || thread.isHidden || Conf['JSON Index'] && Conf['Index Mode'] === 'catalog') { - return false; - } - ThreadHiding.menu.thread = thread; - return true; - }, - subEntries: [ - { - el: apply - }, { - el: makeStub - } - ] - }); - div = $.el('a', { - className: 'show-thread-link', - textContent: 'Show', - href: 'javascript:;' - }); - $.on(div, 'click', ThreadHiding.menu.show); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(arg) { - var isReply, thread; - thread = arg.thread, isReply = arg.isReply; - if (isReply || !thread.isHidden || Conf['JSON Index'] && Conf['Index Mode'] === 'catalog') { - return false; - } - ThreadHiding.menu.thread = thread; - return true; - } - }); - hideStubLink = $.el('a', { - textContent: 'Hide stub', - href: 'javascript:;' - }); - $.on(hideStubLink, 'click', ThreadHiding.menu.hideStub); - return Menu.menu.addEntry({ - el: hideStubLink, - order: 15, - open: function(arg) { - var isReply, thread; - thread = arg.thread, isReply = arg.isReply; - if (isReply || !thread.isHidden || Conf['JSON Index'] && Conf['Index Mode'] === 'catalog') { - return false; - } - return ThreadHiding.menu.thread = thread; - } - }); - }, - hide: function() { - var makeStub, thread; - makeStub = $('input', this.parentNode).checked; - thread = ThreadHiding.menu.thread; - ThreadHiding.hide(thread, makeStub); - ThreadHiding.saveHiddenState(thread, makeStub); - return $.event('CloseMenu'); - }, - show: function() { - var thread; - thread = ThreadHiding.menu.thread; - ThreadHiding.show(thread); - ThreadHiding.saveHiddenState(thread); - return $.event('CloseMenu'); - }, - hideStub: function() { - var thread; - thread = ThreadHiding.menu.thread; - ThreadHiding.show(thread); - ThreadHiding.hide(thread, false); - ThreadHiding.saveHiddenState(thread, false); - $.event('CloseMenu'); - } - }, - makeButton: function(thread, type) { - var a; - a = $.el('a', { - className: type + "-thread-button", - href: 'javascript:;' - }); - $.extend(a, {innerHTML: ""}); - a.dataset.fullID = thread.fullID; - $.on(a, 'click', ThreadHiding.toggle); - return a; - }, - makeStub: function(thread, root) { - var a, numReplies, summary, threadDivider; - numReplies = $$(g.SITE.selectors.replyOriginal, root).length; - if (summary = $(g.SITE.selectors.summary, root)) { - numReplies += +summary.textContent.match(/\d+/); - } - a = ThreadHiding.makeButton(thread, 'show'); - $.add(a, $.tn(" " + thread.OP.info.nameBlock + " (" + (numReplies === 1 ? '1 reply' : numReplies + " replies") + ")")); - thread.stub = $.el('div', { - className: 'stub' - }); - if (Conf['Menu']) { - $.add(thread.stub, [a, Menu.makeButton(thread.OP)]); - } else { - $.add(thread.stub, a); - } - $.prepend(root, thread.stub); - if ((threadDivider = $(g.SITE.selectors.threadDivider, root))) { - return $.addClass(threadDivider, 'threadDivider'); - } - }, - saveHiddenState: function(thread, makeStub) { - if (thread.isHidden) { - ThreadHiding.db.set({ - boardID: thread.board.ID, - threadID: thread.ID, - val: { - makeStub: makeStub - } - }); - } else { - ThreadHiding.db["delete"]({ - boardID: thread.board.ID, - threadID: thread.ID - }); - } - return ThreadHiding.catalogSet(thread.board); - }, - toggle: function(thread) { - if (!(thread instanceof Thread)) { - thread = g.threads.get(this.dataset.fullID); - } - if (thread.isHidden) { - ThreadHiding.show(thread); - } else { - ThreadHiding.hide(thread); - } - return ThreadHiding.saveHiddenState(thread); - }, - hide: function(thread, makeStub) { - var threadRoot; - if (makeStub == null) { - makeStub = Conf['Stubs']; - } - if (thread.isHidden) { - return; - } - threadRoot = thread.nodes.root; - thread.isHidden = true; - Index.updateHideLabel(); - if (thread.catalogView && !Index.showHiddenThreads) { - $.rm(thread.catalogView.nodes.root); - $.event('PostsRemoved', null, Index.root); - } - if (!makeStub) { - return threadRoot.hidden = true; - } - return ThreadHiding.makeStub(thread, threadRoot); - }, - show: function(thread) { - var threadRoot; - if (thread.stub) { - $.rm(thread.stub); - delete thread.stub; - } - threadRoot = thread.nodes.root; - threadRoot.hidden = thread.isHidden = false; - Index.updateHideLabel(); - if (thread.catalogView && Index.showHiddenThreads) { - $.rm(thread.catalogView.nodes.root); - return $.event('PostsRemoved', null, Index.root); - } - } - }; - - return ThreadHiding; - -}).call(this); - -BoardConfig = (function() { - var BoardConfig; - - BoardConfig = { - cbs: [], - init: function() { - var boards, now, ref; - if (g.SITE.software !== 'yotsuba') { - return; - } - now = Date.now(); - if (!((now - 2 * $.HOUR < (ref = Conf['boardConfig'].lastChecked || 0) && ref <= now))) { - return $.ajax(location.protocol + "//a.4cdn.org/boards.json", { - onloadend: this.load - }); - } else { - boards = Conf['boardConfig'].boards; - return this.set(boards); - } - }, - load: function() { - var board, boards, err, i, len, ref; - if (this.status === 200 && this.response && this.response.boards) { - boards = $.dict(); - ref = this.response.boards; - for (i = 0, len = ref.length; i < len; i++) { - board = ref[i]; - boards[board.board] = board; - } - $.set('boardConfig', { - boards: boards, - lastChecked: Date.now() - }); - } else { - boards = Conf['boardConfig'].boards; - err = (function() { - switch (this.status) { - case 0: - return 'Connection Error'; - case 200: - return 'Invalid Data'; - default: - return "Error " + this.statusText + " (" + this.status + ")"; - } - }).call(this); - new Notice('warning', "Failed to load board configuration. " + err, 20); - } - return BoardConfig.set(boards); - }, - set: function(boards1) { - var ID, board, cb, i, len, ref, ref1; - this.boards = boards1; - ref = g.boards; - for (ID in ref) { - board = ref[ID]; - board.config = this.boards[ID] || {}; - } - ref1 = this.cbs; - for (i = 0, len = ref1.length; i < len; i++) { - cb = ref1[i]; - $.queueTask(cb); - } - }, - ready: function(cb) { - if (this.boards) { - return cb(); - } else { - return this.cbs.push(cb); - } - }, - sfwBoards: function(sfw) { - var board, data, ref, results; - ref = this.boards || Conf['boardConfig'].boards; - results = []; - for (board in ref) { - data = ref[board]; - if (!!data.ws_board === sfw) { - results.push(board); - } - } - return results; - }, - isSFW: function(board) { - var ref; - return !!((ref = (this.boards || Conf['boardConfig'].boards)[board]) != null ? ref.ws_board : void 0); - }, - domain: function(board) { - return "boards." + (BoardConfig.isSFW(board) ? '4channel' : '4chan') + ".org"; - }, - isArchived: function(board) { - var data; - data = (this.boards || Conf['boardConfig'].boards)[board]; - return !data || data.is_archived; - }, - noAudio: function(boardID) { - var boards; - if (g.SITE.software !== 'yotsuba') { - return false; - } - boards = this.boards || Conf['boardConfig'].boards; - return boards && boards[boardID] && !boards[boardID].webm_audio; - }, - title: function(boardID) { - var ref, ref1; - return ((ref = this.boards || Conf['boardConfig'].boards) != null ? (ref1 = ref[boardID]) != null ? ref1.title : void 0 : void 0) || ''; - } - }; - - return BoardConfig; - -}).call(this); - -Get = (function() { - var Get, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Get = { - url: function() { - var IDs, args, f, site, type; - type = arguments[0], IDs = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - if ((site = g.sites[IDs.siteID]) && (f = $.getOwn(site.urls, type))) { - return f.apply(null, [IDs].concat(slice.call(args))); - } else { - return void 0; - } - }, - threadExcerpt: function(thread) { - var OP, excerpt, ref, ref1; - OP = thread.OP; - excerpt = ("/" + (decodeURIComponent(thread.board.ID)) + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP)); - if (excerpt.length > 73) { - return excerpt.slice(0, 70) + "..."; - } - return excerpt; - }, - threadFromRoot: function(root) { - var board; - if (root == null) { - return null; - } - board = root.dataset.board; - return g.threads.get((board ? encodeURIComponent(board) : g.BOARD.ID) + "." + (root.id.match(/\d*$/)[0])); - }, - threadFromNode: function(node) { - return Get.threadFromRoot($.x("ancestor-or-self::" + g.SITE.xpath.thread, node)); - }, - postFromRoot: function(root) { - var index, post; - if (root == null) { - return null; - } - post = g.posts.get(root.dataset.fullID); - index = root.dataset.clone; - if (index) { - return post.clones[+index]; - } else { - return post; - } - }, - postFromNode: function(root) { - return Get.postFromRoot($.x("ancestor-or-self::" + g.SITE.xpath.postContainer + "[1]", root)); - }, - postDataFromLink: function(link) { - var boardID, match, postID, ref, ref1, threadID; - if (link.dataset.postID) { - ref = link.dataset, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - threadID || (threadID = 0); - } else { - match = link.href.match(g.SITE.regexp.quotelink); - ref1 = match.slice(1), boardID = ref1[0], threadID = ref1[1], postID = ref1[2]; - postID || (postID = threadID); - } - return { - boardID: boardID, - threadID: +threadID, - postID: +postID - }; - }, - allQuotelinksLinkingTo: function(post) { - var fullID, handleQuotes, i, len, posts, qPost, quote, quotelinks, ref; - quotelinks = []; - posts = g.posts; - fullID = post.fullID; - handleQuotes = function(qPost, type) { - var clone, i, len, ref; - quotelinks.push.apply(quotelinks, qPost.nodes[type]); - ref = qPost.clones; - for (i = 0, len = ref.length; i < len; i++) { - clone = ref[i]; - quotelinks.push.apply(quotelinks, clone.nodes[type]); - } - }; - posts.forEach(function(qPost) { - if (indexOf.call(qPost.quotes, fullID) >= 0) { - return handleQuotes(qPost, 'quotelinks'); - } - }); - if (Conf['Quote Backlinks']) { - ref = post.quotes; - for (i = 0, len = ref.length; i < len; i++) { - quote = ref[i]; - if (qPost = posts.get(quote)) { - handleQuotes(qPost, 'backlinks'); - } - } - } - return quotelinks.filter(function(quotelink) { - var boardID, postID, ref1; - ref1 = Get.postDataFromLink(quotelink), boardID = ref1.boardID, postID = ref1.postID; - return boardID === post.board.ID && postID === post.ID; - }); - } - }; - - return Get; - -}).call(this); - -Header = (function() { - var Header, - slice = [].slice; - - Header = { - init: function() { - var barFixedToggler, barPositionToggler, box, cs, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, menuButton, scrollHeaderToggler, shortcutToggler; - $.onExists(doc, 'body', (function(_this) { - return function() { - if (!Main.isThisPageLegit()) { - return; - } - $.add(_this.bar, [_this.noticesRoot, _this.toggle]); - $.prepend(d.body, _this.bar); - $.add(d.body, Header.hover); - return _this.setBarPosition(Conf['Bottom Header']); - }; - })(this)); - this.menu = new UI.Menu('header'); - menuButton = $.el('span', { - className: 'menu-button' - }); - $.extend(menuButton, {innerHTML: ""}); - box = UI.checkbox; - barFixedToggler = box('Fixed Header', 'Fixed Header'); - headerToggler = box('Header auto-hide', 'Auto-hide header'); - scrollHeaderToggler = box('Header auto-hide on scroll', 'Auto-hide header on scroll'); - barPositionToggler = box('Bottom Header', 'Bottom header'); - linkJustifyToggler = box('Centered links', 'Centered links'); - customNavToggler = box('Custom Board Navigation', 'Custom board navigation'); - footerToggler = box('Bottom Board List', 'Hide bottom board list'); - shortcutToggler = box('Shortcut Icons', 'Shortcut Icons'); - editCustomNav = $.el('a', { - textContent: 'Edit custom board navigation', - href: 'javascript:;' - }); - this.barFixedToggler = barFixedToggler.firstElementChild; - this.scrollHeaderToggler = scrollHeaderToggler.firstElementChild; - this.barPositionToggler = barPositionToggler.firstElementChild; - this.linkJustifyToggler = linkJustifyToggler.firstElementChild; - this.headerToggler = headerToggler.firstElementChild; - this.footerToggler = footerToggler.firstElementChild; - this.shortcutToggler = shortcutToggler.firstElementChild; - this.customNavToggler = customNavToggler.firstElementChild; - $.on(menuButton, 'click', this.menuToggle); - $.on(this.headerToggler, 'change', this.toggleBarVisibility); - $.on(this.barFixedToggler, 'change', this.toggleBarFixed); - $.on(this.barPositionToggler, 'change', this.toggleBarPosition); - $.on(this.scrollHeaderToggler, 'change', this.toggleHideBarOnScroll); - $.on(this.linkJustifyToggler, 'change', this.toggleLinkJustify); - $.on(this.footerToggler, 'change', this.toggleFooterVisibility); - $.on(this.shortcutToggler, 'change', this.toggleShortcutIcons); - $.on(this.customNavToggler, 'change', this.toggleCustomNav); - $.on(editCustomNav, 'click', this.editCustomNav); - this.setBarFixed(Conf['Fixed Header']); - this.setHideBarOnScroll(Conf['Header auto-hide on scroll']); - this.setBarVisibility(Conf['Header auto-hide']); - this.setLinkJustify(Conf['Centered links']); - this.setShortcutIcons(Conf['Shortcut Icons']); - this.setFooterVisibility(Conf['Bottom Board List']); - $.sync('Fixed Header', this.setBarFixed); - $.sync('Header auto-hide on scroll', this.setHideBarOnScroll); - $.sync('Bottom Header', this.setBarPosition); - $.sync('Shortcut Icons', this.setShortcutIcons); - $.sync('Header auto-hide', this.setBarVisibility); - $.sync('Centered links', this.setLinkJustify); - $.sync('Bottom Board List', this.setFooterVisibility); - this.addShortcut('menu', menuButton, 900); - this.menu.addEntry({ - el: $.el('span', { - textContent: 'Header' - }), - order: 107, - subEntries: [ - { - el: barFixedToggler - }, { - el: headerToggler - }, { - el: scrollHeaderToggler - }, { - el: barPositionToggler - }, { - el: linkJustifyToggler - }, { - el: footerToggler - }, { - el: shortcutToggler - }, { - el: customNavToggler - }, { - el: editCustomNav - } - ] - }); - $.on(window, 'load popstate', Header.hashScroll); - $.on(d, 'CreateNotification', this.createNotification); - this.setBoardList(); - $.onExists(doc, g.SITE.selectors.boardList + " + *", Header.generateFullBoardList); - Main.ready(function() { - var a, absbot, footer, i, len, ref; - if (g.SITE.software === 'yotsuba' && !(footer = $.id('boardNavDesktopFoot'))) { - if (!(absbot = $.id('absbot'))) { - return; - } - footer = $.id('boardNavDesktop').cloneNode(true); - footer.id = 'boardNavDesktopFoot'; - $('#navtopright', footer).id = 'navbotright'; - $('#settingsWindowLink', footer).id = 'settingsWindowLinkBot'; - $.before(absbot, footer); - $.global(function() { - return window.cloneTopNav = function() {}; - }); - } - if ((Header.bottomBoardList = $(g.SITE.selectors.boardListBottom))) { - ref = $$('a', Header.bottomBoardList); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - if (a.hostname === location.hostname && a.pathname.split('/')[1] === g.BOARD.ID) { - a.className = 'current'; - } - } - return CatalogLinks.setLinks(Header.bottomBoardList); - } - }); - if (g.SITE.software === 'yotsuba' && (g.VIEW === 'catalog' || !Conf['Disable Native Extension'])) { - cs = $.el('a', { - href: 'javascript:;' - }); - if (g.VIEW === 'catalog') { - cs.title = cs.textContent = 'Catalog Settings'; - cs.className = 'fa fa-book'; - } else { - cs.title = cs.textContent = '4chan Settings'; - cs.className = 'native-settings'; - } - $.on(cs, 'click', function() { - return $.id('settingsWindowLink').click(); - }); - this.addShortcut('native', cs, 810); - } - return this.enableDesktopNotifications(); - }, - bar: $.el('div', { - id: 'header-bar' - }), - noticesRoot: $.el('div', { - id: 'notifications' - }), - shortcuts: $.el('span', { - id: 'shortcuts' - }), - hover: $.el('div', { - id: 'hoverUI' - }), - toggle: $.el('div', { - id: 'scroll-marker' - }), - setBoardList: function() { - var boardList, btn; - Header.boardList = boardList = $.el('span', { - id: 'board-list' - }); - $.extend(boardList, {innerHTML: ""}); - btn = $('.hide-board-list-button', boardList); - $.on(btn, 'click', Header.toggleBoardList); - $.prepend(Header.bar, [Header.boardList, Header.shortcuts]); - Header.setCustomNav(Conf['Custom Board Navigation']); - Header.generateBoardList(Conf['boardnav']); - $.sync('Custom Board Navigation', Header.setCustomNav); - return $.sync('boardnav', Header.generateBoardList); - }, - generateFullBoardList: function() { - var a, fullBoardList, i, len, nodes, ref; - if (g.SITE.transformBoardList) { - nodes = g.SITE.transformBoardList(); - } else { - nodes = slice.call($(g.SITE.selectors.boardList).cloneNode(true).childNodes); - } - fullBoardList = $('.boardList', Header.boardList); - $.add(fullBoardList, nodes); - ref = $$('a', fullBoardList); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - if (a.hostname === location.hostname && a.pathname.split('/')[1] === g.BOARD.ID) { - a.className = 'current'; - } - } - return CatalogLinks.setLinks(fullBoardList); - }, - generateBoardList: function(boardnav) { - var list, nodes, re, t; - list = $('#custom-board-list', Header.boardList); - $.rmAll(list); - if (!boardnav) { - return; - } - boardnav = boardnav.replace(/(\r\n|\n|\r)/g, ' '); - re = /[\w@]+(-(all|title|replace|full|index|catalog|archive|expired|nt|(mode|sort|text):"[^"]+"(,"[^"]+")?))*|[^\w@]+/g; - nodes = (function() { - var i, len, ref, results; - ref = boardnav.match(re); - results = []; - for (i = 0, len = ref.length; i < len; i++) { - t = ref[i]; - results.push(Header.mapCustomNavigation(t)); - } - return results; - })(); - $.add(list, nodes); - return CatalogLinks.setLinks(list); - }, - mapCustomNavigation: function(t) { - var a, boardID, href, indexOptions, m, ref, ref1, text, url, urlIC; - if (/^[^\w@]/.test(t)) { - return $.tn(t); - } - text = url = null; - t = t.replace(/-text:"([^"]+)"(?:,"([^"]+)")?/g, function(m0, m1, m2) { - text = m1; - url = m2; - return ''; - }); - indexOptions = []; - t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { - indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); - return ''; - }); - indexOptions = indexOptions.join('/'); - if (/^toggle-all/.test(t)) { - a = $.el('a', { - className: 'show-board-list-button', - textContent: text || '+', - href: 'javascript:;' - }); - $.on(a, 'click', Header.toggleBoardList); - return a; - } - if (/^external/.test(t)) { - a = $.el('a', { - href: url || 'javascript:;', - textContent: text || '+', - className: 'external' - }); - if (/-nt/.test(t)) { - a.target = '_blank'; - a.rel = 'noopener'; - } - return a; - } - boardID = t.split('-')[0]; - if (boardID === 'current') { - if ((ref = location.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') { - boardID = g.BOARD.ID; - } else { - a = $.el('a', { - href: "/" + g.BOARD.ID + "/", - textContent: text || decodeURIComponent(g.BOARD.ID), - className: 'current' - }); - if (/-nt/.test(t)) { - a.target = '_blank'; - a.rel = 'noopener'; - } - if (/-index/.test(t)) { - a.dataset.only = 'index'; - } else if (/-catalog/.test(t)) { - a.dataset.only = 'catalog'; - a.href += 'catalog.html'; - } else if (/-(archive|expired)/.test(t)) { - a = a.firstChild; - } - return a; - } - } - a = (function() { - var ref1, urlV; - if (boardID === '@') { - return $.el('a', { - href: 'https://twitter.com/4chan', - title: '4chan Twitter', - textContent: '@' - }); - } - a = $.el('a', { - href: "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/", - textContent: boardID, - title: BoardConfig.title(boardID) - }); - if (((ref1 = g.VIEW) === 'catalog' || ref1 === 'archive') && (urlV = Get.url(g.VIEW, { - siteID: '4chan.org', - boardID: boardID - }))) { - a.href = urlV; - } - if (a.hostname === location.hostname && boardID === g.BOARD.ID) { - a.className = 'current'; - } - return a; - })(); - a.textContent = /-title/.test(t) || /-replace/.test(t) && a.hostname === location.hostname && boardID === g.BOARD.ID ? a.title || a.textContent : /-full/.test(t) ? ("/" + boardID + "/") + (a.title ? " - " + a.title : '') : text || boardID; - if (m = t.match(/-(index|catalog)/)) { - urlIC = CatalogLinks[m[1]]({ - siteID: '4chan.org', - boardID: boardID - }); - if (urlIC) { - a.dataset.only = m[1]; - a.href = urlIC; - if (m[1] === 'catalog') { - $.addClass(a, 'catalog'); - } - } else { - return a.firstChild; - } - } - if (Conf['JSON Index'] && indexOptions) { - a.dataset.indexOptions = indexOptions; - if (((ref1 = a.hostname) === 'boards.4chan.org' || ref1 === 'boards.4channel.org') && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + indexOptions; - } - } - if (/-archive/.test(t)) { - if (href = Redirect.to('board', { - boardID: boardID - })) { - a.href = href; - } else { - return a.firstChild; - } - } - if (/-expired/.test(t)) { - if (BoardConfig.isArchived(boardID)) { - a.href = "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/archive"; - } else { - return a.firstChild; - } - } - if (/-nt/.test(t)) { - a.target = '_blank'; - a.rel = 'noopener'; - } - if (boardID === '@') { - $.addClass(a, 'navSmall'); - } - return a; - }, - toggleBoardList: function() { - var bar, custom, full, showBoardList; - bar = Header.bar; - custom = $('#custom-board-list', bar); - full = $('#full-board-list', bar); - showBoardList = !full.hidden; - custom.hidden = !showBoardList; - return full.hidden = showBoardList; - }, - setLinkJustify: function(centered) { - Header.linkJustifyToggler.checked = centered; - if (centered) { - return $.addClass(doc, 'centered-links'); - } else { - return $.rmClass(doc, 'centered-links'); - } - }, - toggleLinkJustify: function() { - var centered; - $.event('CloseMenu'); - centered = this.nodeName === 'INPUT' ? this.checked : void 0; - Header.setLinkJustify(centered); - return $.set('Centered links', centered); - }, - setBarFixed: function(fixed) { - Header.barFixedToggler.checked = fixed; - if (fixed) { - $.addClass(doc, 'fixed'); - return $.addClass(Header.bar, 'dialog'); - } else { - $.rmClass(doc, 'fixed'); - return $.rmClass(Header.bar, 'dialog'); - } - }, - toggleBarFixed: function() { - $.event('CloseMenu'); - Header.setBarFixed(this.checked); - Conf['Fixed Header'] = this.checked; - return $.set('Fixed Header', this.checked); - }, - setShortcutIcons: function(show) { - Header.shortcutToggler.checked = show; - if (show) { - return $.addClass(doc, 'shortcut-icons'); - } else { - return $.rmClass(doc, 'shortcut-icons'); - } - }, - toggleShortcutIcons: function() { - $.event('CloseMenu'); - Header.setShortcutIcons(this.checked); - Conf['Shortcut Icons'] = this.checked; - return $.set('Shortcut Icons', this.checked); - }, - setBarVisibility: function(hide) { - Header.headerToggler.checked = hide; - $.event('CloseMenu'); - (hide ? $.addClass : $.rmClass)(Header.bar, 'autohide'); - return (hide ? $.addClass : $.rmClass)(doc, 'autohide'); - }, - toggleBarVisibility: function() { - var hide, message; - hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide'); - Conf['Header auto-hide'] = hide; - $.set('Header auto-hide', hide); - Header.setBarVisibility(hide); - message = "The header bar will " + (hide ? 'automatically hide itself.' : 'remain visible.'); - return new Notice('info', message, 2); - }, - setHideBarOnScroll: function(hide) { - Header.scrollHeaderToggler.checked = hide; - if (hide) { - $.on(window, 'scroll', Header.hideBarOnScroll); - return; - } - $.off(window, 'scroll', Header.hideBarOnScroll); - $.rmClass(Header.bar, 'scroll'); - return Header.bar.classList.toggle('autohide', Conf['Header auto-hide']); - }, - toggleHideBarOnScroll: function() { - var hide; - hide = this.checked; - $.cb.checked.call(this); - return Header.setHideBarOnScroll(hide); - }, - hideBarOnScroll: function() { - var offsetY; - offsetY = window.pageYOffset; - if (offsetY > (Header.previousOffset || 0)) { - $.addClass(Header.bar, 'autohide', 'scroll'); - } else { - $.rmClass(Header.bar, 'autohide', 'scroll'); - } - return Header.previousOffset = offsetY; - }, - setBarPosition: function(bottom) { - var args, ref; - if ((ref = Header.barPositionToggler) != null) { - ref.checked = bottom; - } - $.event('CloseMenu'); - args = bottom ? ['bottom-header', 'top-header', 'after'] : ['top-header', 'bottom-header', 'add']; - $.addClass(doc, args[0]); - $.rmClass(doc, args[1]); - return $[args[2]](Header.bar, Header.noticesRoot); - }, - toggleBarPosition: function() { - $.cb.checked.call(this); - return Header.setBarPosition(this.checked); - }, - setFooterVisibility: function(hide) { - Header.footerToggler.checked = hide; - return doc.classList.toggle('hide-bottom-board-list', hide); - }, - toggleFooterVisibility: function() { - var hide, message; - $.event('CloseMenu'); - hide = this.nodeName === 'INPUT' ? this.checked : $.hasClass(doc, 'hide-bottom-board-list'); - Header.setFooterVisibility(hide); - $.set('Bottom Board List', hide); - message = hide ? 'The bottom navigation will now be hidden.' : 'The bottom navigation will remain visible.'; - return new Notice('info', message, 2); - }, - setCustomNav: function(show) { - var btn, cust, full, ref; - Header.customNavToggler.checked = show; - cust = $('#custom-board-list', Header.bar); - full = $('#full-board-list', Header.bar); - btn = $('.hide-board-list-container', full); - return ref = show ? [false, true, false] : [true, false, true], cust.hidden = ref[0], full.hidden = ref[1], btn.hidden = ref[2], ref; - }, - toggleCustomNav: function() { - $.cb.checked.call(this); - return Header.setCustomNav(this.checked); - }, - editCustomNav: function() { - var settings; - Settings.open('Advanced'); - settings = $.id('fourchanx-settings'); - return $('[name=boardnav]', settings).focus(); - }, - hashScroll: function(e) { - var el, hash; - if (e) { - if (e.state) { - return; - } - if (!history.state) { - history.replaceState({}, ''); - } - } - if ((hash = location.hash.slice(1))) { - ReplyPruning.showIfHidden(hash); - if ((el = $.id(hash))) { - return $.queueTask(function() { - return Header.scrollTo(el); - }); - } - } - }, - scrollTo: function(root, down, needed) { - var height, x; - if (!root.offsetParent) { - return; - } - if (down) { - x = Header.getBottomOf(root); - if (Conf['Fixed Header'] && Conf['Header auto-hide on scroll'] && Conf['Bottom header']) { - height = Header.bar.getBoundingClientRect().height; - if (x <= 0) { - if (!Header.isHidden()) { - x += height; - } - } else { - if (Header.isHidden()) { - x -= height; - } - } - } - if (!(needed && x >= 0)) { - return window.scrollBy(0, -x); - } - } else { - x = Header.getTopOf(root); - if (Conf['Fixed Header'] && Conf['Header auto-hide on scroll'] && !Conf['Bottom header']) { - height = Header.bar.getBoundingClientRect().height; - if (x >= 0) { - if (!Header.isHidden()) { - x += height; - } - } else { - if (Header.isHidden()) { - x -= height; - } - } - } - if (!(needed && x >= 0)) { - return window.scrollBy(0, x); - } - } - }, - scrollToIfNeeded: function(root, down) { - return Header.scrollTo(root, down, true); - }, - getTopOf: function(root) { - var headRect, top; - top = root.getBoundingClientRect().top; - if (Conf['Fixed Header'] && !Conf['Bottom Header']) { - headRect = Header.toggle.getBoundingClientRect(); - top -= headRect.top + headRect.height; - } - return top; - }, - getBottomOf: function(root) { - var bottom, clientHeight, headRect; - clientHeight = doc.clientHeight; - bottom = clientHeight - root.getBoundingClientRect().bottom; - if (Conf['Fixed Header'] && Conf['Bottom Header']) { - headRect = Header.toggle.getBoundingClientRect(); - bottom -= clientHeight - headRect.bottom + headRect.height; - } - return bottom; - }, - isNodeVisible: function(node) { - var height; - if (d.hidden || !doc.contains(node)) { - return false; - } - height = node.getBoundingClientRect().height; - return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0; - }, - isHidden: function() { - var top; - top = Header.bar.getBoundingClientRect().top; - if (Conf['Bottom header']) { - return top === doc.clientHeight; - } else { - return top < 0; - } - }, - addShortcut: function(id, el, index) { - var i, item, len, ref, shortcut; - shortcut = $.el('span', { - id: "shortcut-" + id, - className: 'shortcut brackets-wrap' - }); - $.add(shortcut, el); - shortcut.dataset.index = index; - ref = $$('[data-index]', Header.shortcuts); - for (i = 0, len = ref.length; i < len; i++) { - item = ref[i]; - if (!(+item.dataset.index > +index)) { - continue; - } - $.before(item, shortcut); - return; - } - return $.add(Header.shortcuts, shortcut); - }, - rmShortcut: function(el) { - return $.rm(el.parentElement); - }, - menuToggle: function(e) { - return Header.menu.toggle(e, this, g); - }, - createNotification: function(e) { - var content, lifetime, notice, ref, type; - ref = e.detail, type = ref.type, content = ref.content, lifetime = ref.lifetime; - return notice = new Notice(type, content, lifetime); - }, - areNotificationsEnabled: false, - enableDesktopNotifications: function() { - var authorize, disable, el, notice, ref; - if (!(window.Notification && Conf['Desktop Notifications'])) { - return; - } - switch (Notification.permission) { - case 'granted': - Header.areNotificationsEnabled = true; - return; - case 'denied': - return; - } - el = $.el('span', {innerHTML: "4chan X needs your permission to show desktop notifications. [FAQ]
or "}); - ref = $$('button', el), authorize = ref[0], disable = ref[1]; - $.on(authorize, 'click', function() { - return Notification.requestPermission(function(status) { - Header.areNotificationsEnabled = status === 'granted'; - if (status === 'default') { - return; - } - return notice.close(); - }); - }); - $.on(disable, 'click', function() { - $.set('Desktop Notifications', false); - return notice.close(); - }); - return notice = new Notice('info', el); - } - }; - - return Header; - -}).call(this); - -Index = (function() { - var Index, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Index = { - showHiddenThreads: false, - changed: {}, - enabledOn: function(arg) { - var boardID, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return Conf['JSON Index'] && g.sites[siteID].software === 'yotsuba' && boardID !== 'f'; - }, - init: function() { - var arr, entries, i, input, inputs, k, l, label, len1, len2, name, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, select, sortEntry, tRaw, watchSettings; - if (g.VIEW !== 'index') { - return; - } - $.one(d, '4chanXInitFinished', this.cb.initFinished); - $.on(d, 'PostsInserted', this.cb.postsInserted); - if (!this.enabledOn(g.BOARD)) { - return; - } - this.enabled = true; - Callbacks.Post.push({ - name: 'Index Page Numbers', - cb: this.node - }); - Callbacks.CatalogThread.push({ - name: 'Catalog Features', - cb: this.catalogNode - }); - this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; - if ((ref1 = history.state) != null ? ref1.mode : void 0) { - Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; - } - this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; - this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); - this.currentPage = this.getCurrentPage(); - this.processHash(); - $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); - $.on(window, 'popstate', this.cb.popstate); - $.on(d, 'scroll', this.scroll); - $.on(d, 'SortIndex', this.cb.resort); - this.button = $.el('a', { - className: 'fa fa-refresh', - title: 'Refresh', - href: 'javascript:;', - textContent: 'Refresh Index' - }); - $.on(this.button, 'click', function() { - return Index.update(); - }); - Header.addShortcut('index-refresh', this.button, 590); - entries = []; - this.inputs = inputs = $.dict(); - ref4 = Config.Index; - for (name in ref4) { - arr = ref4[name]; - if (!(arr instanceof Array)) { - continue; - } - label = UI.checkbox(name, "" + name[0] + (name.slice(1).toLowerCase())); - label.title = arr[1]; - entries.push({ - el: label - }); - input = label.firstChild; - $.on(input, 'change', $.cb.checked); - inputs[name] = input; - } - $.on(inputs['Show Replies'], 'change', this.cb.replies); - $.on(inputs['Catalog Hover Expand'], 'change', this.cb.hover); - $.on(inputs['Pin Watched Threads'], 'change', this.cb.resort); - $.on(inputs['Anchor Hidden Threads'], 'change', this.cb.resort); - watchSettings = function(e) { - if ((input = $.getOwn(inputs, e.target.name))) { - input.checked = e.target.checked; - return $.event('change', null, input); - } - }; - $.on(d, 'OpenSettings', function() { - return $.on($.id('fourchanx-settings'), 'change', watchSettings); - }); - sortEntry = UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object'); - sortEntry.title = 'Set the sorting order of each board independently.'; - $.on(sortEntry.firstChild, 'change', this.cb.perBoardSort); - entries.splice(3, 0, { - el: sortEntry - }); - Header.menu.addEntry({ - el: $.el('span', { - textContent: 'Index Navigation' - }), - order: 100, - subEntries: entries - }); - this.navLinks = $.el('div', { - className: 'navLinks json-index' - }); - $.extend(this.navLinks, {innerHTML: "Index Catalog Archive Bottom ×"}); - $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); - if (!BoardConfig.isArchived(g.BOARD.ID)) { - $('.archlistlink', this.navLinks).hidden = true; - } - $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); - this.searchInput = $('#index-search', this.navLinks); - this.setupSearch(); - $.on(this.searchInput, 'input', this.onSearchInput); - $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); - this.hideLabel = $('#hidden-label', this.navLinks); - $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); - this.selectRev = $('#index-rev', this.navLinks); - this.selectMode = $('#index-mode', this.navLinks); - this.selectSort = $('#index-sort', this.navLinks); - this.selectSize = $('#index-size', this.navLinks); - $.on(this.selectRev, 'change', this.cb.sort); - $.on(this.selectMode, 'change', this.cb.mode); - $.on(this.selectSort, 'change', this.cb.sort); - $.on(this.selectSize, 'change', $.cb.value); - $.on(this.selectSize, 'change', this.cb.size); - ref5 = [this.selectMode, this.selectSize]; - for (k = 0, len1 = ref5.length; k < len1; k++) { - select = ref5[k]; - select.value = Conf[select.name]; - } - this.selectRev.checked = /-rev$/.test(Index.currentSort); - this.selectSort.value = Index.currentSort.replace(/-rev$/, ''); - this.lastLongOptions = $('#lastlong-options', this.navLinks); - this.lastLongInputs = $$('input', this.lastLongOptions); - this.lastLongThresholds = [0, 0]; - this.lastLongOptions.hidden = this.selectSort.value !== 'lastlong'; - ref6 = this.lastLongInputs; - for (i = l = 0, len2 = ref6.length; l < len2; i = ++l) { - input = ref6[i]; - $.on(input, 'change', this.cb.lastLongThresholds); - tRaw = Conf["Last Long Reply Thresholds " + i]; - input.value = this.lastLongThresholds[i] = typeof tRaw === 'object' ? (ref7 = tRaw[g.BOARD.ID]) != null ? ref7 : 100 : tRaw; - } - this.root = $.el('div', { - className: 'board json-index' - }); - $.on(this.root, 'click', this.cb.hoverToggle); - this.cb.size(); - this.cb.hover(); - this.pagelist = $.el('div', { - className: 'pagelist json-index' - }); - $.extend(this.pagelist, {innerHTML: "
"}); - $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); - $.on(this.pagelist, 'click', this.cb.pageNav); - this.update(true); - $.onExists(doc, 'title + *', function() { - return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); - }); - $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { - var board, el, len3, m, ref8, timeEl, topNavPos; - g.SITE.Build.hat = $('.board > .thread > img:first-child'); - if (g.SITE.Build.hat) { - g.BOARD.threads.forEach(function(thread) { - if (thread.nodes.root) { - return $.prepend(thread.nodes.root, g.SITE.Build.hat.cloneNode(false)); - } - }); - $.addClass(doc, 'hats-enabled'); - $.addStyle(".catalog-thread::after {background-image: url(" + g.SITE.Build.hat.src + ");}"); - } - board = $('.board'); - $.replace(board, Index.root); - if (Index.loaded) { - $.event('PostsInserted', null, Index.root); - } - try { - d.implementation.createDocument(null, null, null).appendChild(board); - } catch (error) {} - ref8 = $$('.navLinks'); - for (m = 0, len3 = ref8.length; m < len3; m++) { - el = ref8[m]; - $.rm(el); - } - $.rm($.id('ctrl-top')); - topNavPos = $.id('delform').previousElementSibling; - $.before(topNavPos, $.el('hr')); - $.before(topNavPos, Index.navLinks); - timeEl = $('#index-last-refresh time', Index.navLinks); - if (timeEl.dataset.utc) { - return RelativeDates.update(timeEl); - } - }); - return Main.ready(function() { - var pagelist; - if ((pagelist = $('.pagelist'))) { - $.replace(pagelist, Index.pagelist); - } - return $.rmClass(doc, 'index-loading'); - }); - }, - scroll: function() { - var pageNum, threadIDs; - if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { - return; - } - if (Index.pageNum == null) { - Index.pageNum = Index.currentPage; - } - pageNum = ++Index.pageNum; - if (pageNum > Index.pagesNum) { - return Index.endNotice(); - } - threadIDs = Index.threadsOnPage(pageNum); - return Index.buildStructure(threadIDs); - }, - endNotice: (function() { - var notify, reset; - notify = false; - reset = function() { - return notify = false; - }; - return function() { - if (notify) { - return; - } - notify = true; - new Notice('info', "Last page reached.", 2); - return setTimeout(reset, 3 * $.SECOND); - }; - })(), - menu: { - init: function() { - if (!(g.VIEW === 'index' && Conf['Menu'] && Conf['Thread Hiding Link'] && Index.enabledOn(g.BOARD))) { - return; - } - return Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, {innerHTML: "Shift+click"}), - order: 20, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; - if (this.cb) { - $.off(this.el, 'click', this.cb); - } - this.cb = function() { - $.event('CloseMenu'); - return Index.toggleHide(thread); - }; - $.on(this.el, 'click', this.cb); - return true; - } - }); - } - }, - node: function() { - if (this.isReply || this.isClone || !(Index.threadPosition[this.ID] != null)) { - return; - } - return this.thread.setPage(Math.floor(Index.threadPosition[this.ID] / Index.threadsNumPerPage) + 1); - }, - catalogNode: function() { - return $.on(this.nodes.root, 'mousedown click', (function(_this) { - return function(e) { - if (!(e.button === 0 && e.shiftKey)) { - return; - } - if (e.type === 'click') { - Index.toggleHide(_this.thread); - } - return e.preventDefault(); - }; - })(this)); - }, - toggleHide: function(thread) { - if (Index.showHiddenThreads) { - ThreadHiding.show(thread); - if (!ThreadHiding.db.get({ - boardID: thread.board.ID, - threadID: thread.ID - })) { - return; - } - } else { - ThreadHiding.hide(thread); - } - return ThreadHiding.saveHiddenState(thread); - }, - cycleSortType: function() { - var i, k, len1, type, types; - types = slice.call(Index.selectSort.options).filter(function(option) { - return !option.disabled; - }); - for (i = k = 0, len1 = types.length; k < len1; i = ++k) { - type = types[i]; - if (type.selected) { - break; - } - } - types[(i + 1) % types.length].selected = true; - return $.event('change', null, Index.selectSort); - }, - cb: { - initFinished: function() { - Index.initFinishedFired = true; - return $.queueTask(function() { - return Index.cb.postsInserted(); - }); - }, - postsInserted: function() { - var n; - if (!Index.initFinishedFired) { - return; - } - n = 0; - g.posts.forEach(function(post) { - if (!post.isFetchedQuote && !post.indexRefreshSeen && doc.contains(post.nodes.root)) { - post.indexRefreshSeen = true; - return n++; - } - }); - if (n) { - return $.event('IndexRefresh'); - } - }, - toggleHiddenThreads: function() { - $('#hidden-toggle a', Index.navLinks).textContent = (Index.showHiddenThreads = !Index.showHiddenThreads) ? 'Hide' : 'Show'; - Index.sort(); - return Index.buildIndex(); - }, - mode: function() { - Index.pushState({ - mode: this.value - }); - return Index.pageLoad(false); - }, - sort: function() { - var value; - value = Index.selectRev.checked ? Index.selectSort.value + "-rev" : Index.selectSort.value; - Index.pushState({ - sort: value - }); - return Index.pageLoad(false); - }, - resort: function(e) { - var ref; - Index.changed.order = true; - if (!(e != null ? (ref = e.detail) != null ? ref.deferred : void 0 : void 0)) { - return Index.pageLoad(false); - } - }, - perBoardSort: function() { - var i, k; - Conf['Index Sort'] = this.checked ? $.dict() : ''; - Index.saveSort(); - for (i = k = 0; k < 2; i = ++k) { - Conf["Last Long Reply Thresholds " + i] = this.checked ? $.dict() : ''; - Index.saveLastLongThresholds(i); - } - }, - lastLongThresholds: function() { - var i, value; - i = slice.call(this.parentNode.children).indexOf(this); - value = +this.value; - if (!Number.isFinite(value)) { - this.value = Index.lastLongThresholds[i]; - return; - } - Index.lastLongThresholds[i] = value; - Index.saveLastLongThresholds(i); - Index.changed.order = true; - return Index.pageLoad(false); - }, - size: function(e) { - if (Conf['Index Mode'] !== 'catalog') { - $.rmClass(Index.root, 'catalog-small'); - $.rmClass(Index.root, 'catalog-large'); - } else if (Conf['Index Size'] === 'small') { - $.addClass(Index.root, 'catalog-small'); - $.rmClass(Index.root, 'catalog-large'); - } else { - $.addClass(Index.root, 'catalog-large'); - $.rmClass(Index.root, 'catalog-small'); - } - if (e) { - return Index.buildIndex(); - } - }, - replies: function() { - return Index.buildIndex(); - }, - hover: function() { - return doc.classList.toggle('catalog-hover-expand', Conf['Catalog Hover Expand']); - }, - hoverToggle: function(e) { - var input, thread; - if (Conf['Catalog Hover Toggle'] && $.hasClass(doc, 'catalog-mode') && !$.modifiedClick(e) && !$.x('ancestor-or-self::a', e.target)) { - input = Index.inputs['Catalog Hover Expand']; - input.checked = !input.checked; - $.event('change', null, input); - if ((thread = Get.threadFromNode(e.target))) { - Index.cb.catalogReplies.call(thread); - return Index.cb.hoverAdjust.call(thread.OP.nodes); - } - } - }, - popstate: function(e) { - var mode, nCommands, page, ref, searched, sort; - if (e != null ? e.state : void 0) { - ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; - page = Index.getCurrentPage(); - Index.setState({ - search: searched, - mode: mode, - sort: sort, - page: page - }); - return Index.pageLoad(false); - } else { - nCommands = Index.processHash(); - if (Conf['Refreshed Navigation'] && nCommands) { - return Index.update(); - } else { - return Index.pageLoad(); - } - } - }, - pageNav: function(e) { - var a; - if ($.modifiedClick(e)) { - return; - } - switch (e.target.nodeName) { - case 'BUTTON': - e.target.blur(); - a = e.target.parentNode; - break; - case 'A': - a = e.target; - break; - default: - return; - } - if (a.textContent === 'Catalog') { - return; - } - e.preventDefault(); - return Index.userPageNav(+a.pathname.split(/\/+/)[2] || 1); - }, - refreshFront: function() { - Index.pushState({ - page: 1 - }); - return Index.update(); - }, - catalogReplies: function() { - if (Conf['Show Replies'] && $.hasClass(doc, 'catalog-hover-expand') && !this.catalogView.nodes.replies) { - return Index.buildCatalogReplies(this); - } - }, - hoverAdjust: function() { - var rect, style, x; - if (!$.hasClass(doc, 'catalog-hover-expand')) { - return; - } - rect = this.post.getBoundingClientRect(); - if ((x = $.minmax(0, -rect.left, doc.clientWidth - rect.right))) { - style = this.post.style; - style.left = x + "px"; - style.right = (-x) + "px"; - return $.one(this.root, 'mouseleave', function() { - return style.left = style.right = null; - }); - } - } - }, - scrollToIndex: function() { - return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); - }, - getCurrentPage: function() { - return +window.location.pathname.split(/\/+/)[2] || 1; - }, - userPageNav: function(page) { - Index.pushState({ - page: page - }); - if (Conf['Refreshed Navigation']) { - return Index.update(); - } else { - return Index.pageLoad(); - } - }, - hashCommands: { - mode: { - 'paged': 'paged', - 'infinite-scrolling': 'infinite', - 'infinite': 'infinite', - 'all-threads': 'all pages', - 'all-pages': 'all pages', - 'catalog': 'catalog' - }, - sort: { - 'bump-order': 'bump', - 'last-reply': 'lastreply', - 'last-long-reply': 'lastlong', - 'creation-date': 'birth', - 'reply-count': 'replycount', - 'file-count': 'filecount', - 'posts-per-minute': 'activity' - } - }, - processHash: function() { - var command, commands, hash, k, leftover, len1, mode, ref, sort, state; - hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; - state = { - replace: true - }; - commands = hash.slice(1).split('/'); - leftover = []; - for (k = 0, len1 = commands.length; k < len1; k++) { - command = commands[k]; - if ((mode = $.getOwn(Index.hashCommands.mode, command))) { - state.mode = mode; - } else if (command === 'index') { - state.mode = Conf['Previous Index Mode']; - state.page = 1; - } else if ((sort = $.getOwn(Index.hashCommands.sort, command.replace(/-rev$/, '')))) { - state.sort = sort; - if (/-rev$/.test(command)) { - state.sort += '-rev'; - } - } else if (/^s=/.test(command)) { - state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); - } else { - leftover.push(command); - } - } - hash = leftover.join('/'); - if (hash) { - state.hash = "#" + hash; - } - Index.pushState(state); - return commands.length - leftover.length; - }, - pushState: function(state) { - var hash, pageBeforeSearch, pathname, ref, replace, search; - search = state.search, hash = state.hash, replace = state.replace; - pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; - if ((search != null) && search !== Index.search) { - state.page = search ? 1 : pageBeforeSearch || 1; - if (!search) { - pageBeforeSearch = void 0; - } else if (!Index.search) { - pageBeforeSearch = Index.currentPage; - } - } - Index.setState(state); - pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; - hash || (hash = ''); - return history[replace ? 'replaceState' : 'pushState']({ - mode: Conf['Index Mode'], - sort: Index.currentSort, - searched: Index.search, - oldpage: pageBeforeSearch - }, '', location.protocol + "//" + location.host + pathname + hash); - }, - setState: function(arg) { - var hash, mode, page, ref, search, sort; - search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; - if ((search != null) && search !== Index.search) { - Index.changed.search = true; - Index.search = search; - } - if ((mode != null) && mode !== Conf['Index Mode']) { - Index.changed.mode = true; - Conf['Index Mode'] = mode; - $.set('Index Mode', mode); - if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { - Conf['Previous Index Mode'] = mode; - $.set('Previous Index Mode', mode); - } - } - if ((sort != null) && sort !== Index.currentSort) { - Index.changed.sort = true; - Index.currentSort = sort; - Index.saveSort(); - } - if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { - page = 1; - } - if ((page != null) && page !== Index.currentPage) { - Index.changed.page = true; - Index.currentPage = page; - } - if (hash != null) { - return Index.changed.hash = true; - } - }, - savePerBoard: function(key, value) { - if (typeof Conf[key] === 'object') { - Conf[key][g.BOARD.ID] = value; - } else { - Conf[key] = value; - } - return $.set(key, Conf[key]); - }, - saveSort: function() { - return Index.savePerBoard('Index Sort', Index.currentSort); - }, - saveLastLongThresholds: function(i) { - return Index.savePerBoard("Last Long Reply Thresholds " + i, Index.lastLongThresholds[i]); - }, - pageLoad: function(scroll) { - var hash, mode, order, page, ref, search, sort, threads; - if (scroll == null) { - scroll = true; - } - if (!Index.liveThreadData) { - return; - } - ref = Index.changed, threads = ref.threads, order = ref.order, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; - threads || (threads = search); - order || (order = sort); - if (threads || order) { - Index.sort(); - } - if (threads) { - Index.buildPagelist(); - } - if (search) { - Index.setupSearch(); - } - if (mode) { - Index.setupMode(); - } - if (sort) { - Index.setupSort(); - } - if (threads || mode || page || order) { - Index.buildIndex(); - } - if (threads || page) { - Index.setPage(); - } - if (scroll && !hash) { - Index.scrollToIndex(); - } - if (hash) { - Header.hashScroll(); - } - return Index.changed = {}; - }, - setupMode: function() { - var k, len1, mode, ref; - ref = ['paged', 'infinite', 'all pages', 'catalog']; - for (k = 0, len1 = ref.length; k < len1; k++) { - mode = ref[k]; - $[mode === Conf['Index Mode'] ? 'addClass' : 'rmClass'](doc, (mode.replace(/\ /g, '-')) + "-mode"); - } - Index.selectMode.value = Conf['Index Mode']; - Index.cb.size(); - Index.showHiddenThreads = false; - return $('#hidden-toggle a', Index.navLinks).textContent = 'Show'; - }, - setupSort: function() { - Index.selectRev.checked = /-rev$/.test(Index.currentSort); - Index.selectSort.value = Index.currentSort.replace(/-rev$/, ''); - return Index.lastLongOptions.hidden = Index.selectSort.value !== 'lastlong'; - }, - getPagesNum: function() { - if (Index.search) { - return Math.ceil(Index.sortedThreadIDs.length / Index.threadsNumPerPage); - } else { - return Index.pagesNum; - } - }, - getMaxPageNum: function() { - return Math.max(1, Index.getPagesNum()); - }, - buildPagelist: function() { - var a, i, k, maxPageNum, nodes, pagesRoot, ref; - pagesRoot = $('.pages', Index.pagelist); - maxPageNum = Index.getMaxPageNum(); - if (pagesRoot.childElementCount !== maxPageNum) { - nodes = []; - for (i = k = 1, ref = maxPageNum; k <= ref; i = k += 1) { - a = $.el('a', { - textContent: i, - href: i === 1 ? './' : i - }); - nodes.push($.tn('['), a, $.tn('] ')); - } - $.rmAll(pagesRoot); - return $.add(pagesRoot, nodes); - } - }, - setPage: function() { - var a, href, maxPageNum, next, pageNum, pagesRoot, prev, strong; - pageNum = Index.currentPage; - maxPageNum = Index.getMaxPageNum(); - pagesRoot = $('.pages', Index.pagelist); - prev = pagesRoot.previousSibling.firstChild; - next = pagesRoot.nextSibling.firstChild; - href = Math.max(pageNum - 1, 1); - prev.href = href === 1 ? './' : href; - prev.firstChild.disabled = href === pageNum; - href = Math.min(pageNum + 1, maxPageNum); - next.href = href === 1 ? './' : href; - next.firstChild.disabled = href === pageNum; - if (strong = $('strong', pagesRoot)) { - if (+strong.textContent === pageNum) { - return; - } - $.replace(strong, strong.firstChild); - } else { - strong = $.el('strong'); - } - if ((a = pagesRoot.children[pageNum - 1])) { - $.before(a, strong); - return $.add(strong, a); - } - }, - updateHideLabel: function() { - var hiddenCount, k, len1, ref, threadID; - if (!Index.hideLabel) { - return; - } - hiddenCount = 0; - ref = Index.liveThreadIDs; - for (k = 0, len1 = ref.length; k < len1; k++) { - threadID = ref[k]; - if (Index.isHidden(threadID)) { - hiddenCount++; - } - } - if (!hiddenCount) { - Index.hideLabel.hidden = true; - if (Index.showHiddenThreads) { - Index.cb.toggleHiddenThreads(); - } - return; - } - Index.hideLabel.hidden = false; - return $('#hidden-count', Index.navLinks).textContent = hiddenCount === 1 ? '1 hidden thread' : hiddenCount + " hidden threads"; - }, - update: function(firstTime) { - var oldReq; - if ((oldReq = Index.req)) { - delete Index.req; - oldReq.abort(); - } - if (Conf['Index Refresh Notifications']) { - Index.notice || (Index.notice = new Notice('info', 'Refreshing index...')); - Index.nTimeout || (Index.nTimeout = setTimeout(function() { - var ref; - return (ref = Index.notice) != null ? ref.el.lastElementChild.textContent += ' (disable JSON Index if this takes too long)' : void 0; - }, 3 * $.SECOND)); - } else { - Index.nTimeout || (Index.nTimeout = setTimeout(function() { - return Index.notice || (Index.notice = new Notice('info', 'Refreshing index... (disable JSON Index if this takes too long)')); - }, 3 * $.SECOND)); - } - if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { - location.reload(); - return; - } - Index.req = $.whenModified(g.SITE.urls.catalogJSON({ - boardID: g.BOARD.ID - }), 'Index', Index.load); - return $.addClass(Index.button, 'fa-spin'); - }, - load: function() { - var err, nTimeout, notice, ref, timeEl; - if (this !== Index.req) { - return; - } - $.rmClass(Index.button, 'fa-spin'); - notice = Index.notice, nTimeout = Index.nTimeout; - if (nTimeout) { - clearTimeout(nTimeout); - } - delete Index.nTimeout; - delete Index.req; - delete Index.notice; - if ((ref = this.status) !== 200 && ref !== 304) { - err = "Index refresh failed. " + (this.status ? "Error " + this.statusText + " (" + this.status + ")" : 'Connection Error'); - if (notice) { - notice.setType('warning'); - notice.el.lastElementChild.textContent = err; - setTimeout(notice.close, $.SECOND); - } else { - new Notice('warning', err, 1); - } - return; - } - try { - if (this.status === 200) { - Index.parse(this.response); - } else if (this.status === 304) { - Index.pageLoad(); - } - } catch (error) { - err = error; - c.error("Index failure: " + err.message, err.stack); - if (notice) { - notice.setType('error'); - notice.el.lastElementChild.textContent = 'Index refresh failed.'; - setTimeout(notice.close, $.SECOND); - } else { - new Notice('error', 'Index refresh failed.', 1); - } - return; - } - if (notice) { - if (Conf['Index Refresh Notifications']) { - notice.setType('success'); - notice.el.lastElementChild.textContent = 'Index refreshed!'; - setTimeout(notice.close, $.SECOND); - } else { - notice.close(); - } - } - timeEl = $('#index-last-refresh time', Index.navLinks); - timeEl.dataset.utc = Date.parse(this.getResponseHeader('Last-Modified')); - return RelativeDates.update(timeEl); - }, - parse: function(pages) { - $.cleanCache(function(url) { - return /^https?:\/\/a\.4cdn\.org\//.test(url); - }); - Index.parseThreadList(pages); - Index.changed.threads = true; - return Index.pageLoad(); - }, - parseThreadList: function(pages) { - var ID, data, i, k, l, len1, len2, obj, ref, ref1, ref2, reply, results; - Index.pagesNum = pages.length; - Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; - Index.liveThreadData = pages.reduce((function(arr, next) { - return arr.concat(next.threads); - }), []); - Index.liveThreadIDs = Index.liveThreadData.map(function(data) { - return data.no; - }); - Index.liveThreadDict = $.dict(); - Index.threadPosition = $.dict(); - Index.parsedThreads = $.dict(); - Index.replyData = $.dict(); - ref1 = Index.liveThreadData; - for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { - data = ref1[i]; - Index.liveThreadDict[data.no] = data; - Index.threadPosition[data.no] = i; - Index.parsedThreads[data.no] = obj = g.SITE.Build.parseJSON(data, g.BOARD); - obj.filterResults = results = Filter.test(obj); - obj.isOnTop = results.top; - obj.isHidden = results.hide || ThreadHiding.isHidden(obj.boardID, obj.threadID); - if (data.last_replies) { - ref2 = data.last_replies; - for (l = 0, len2 = ref2.length; l < len2; l++) { - reply = ref2[l]; - Index.replyData[g.BOARD + "." + reply.no] = reply; - } - } - } - if (Index.liveThreadData[0]) { - g.SITE.Build.spoilerRange[g.BOARD.ID] = Index.liveThreadData[0].custom_spoiler; - } - g.BOARD.threads.forEach(function(thread) { - var ref3; - if (ref3 = thread.ID, indexOf.call(Index.liveThreadIDs, ref3) < 0) { - return thread.collect(); - } - }); - $.event('IndexUpdate', { - threads: (function() { - var len3, m, ref3, results1; - ref3 = Index.liveThreadIDs; - results1 = []; - for (m = 0, len3 = ref3.length; m < len3; m++) { - ID = ref3[m]; - results1.push(g.BOARD + "." + ID); - } - return results1; - })() - }); - }, - isHidden: function(threadID) { - var thread; - if ((thread = g.BOARD.threads.get(threadID)) && thread.OP && !thread.OP.isFetchedQuote) { - return thread.isHidden; - } else { - return Index.parsedThreads[threadID].isHidden; - } - }, - isHiddenReply: function(threadID, replyData) { - return PostHiding.isHidden(g.BOARD.ID, threadID, replyData.no) || Filter.isHidden(g.SITE.Build.parseJSON(replyData, g.BOARD)); - }, - buildThreads: function(threadIDs, isCatalog, withReplies) { - var ID, OP, err, errors, isStale, k, lastPost, len1, newPosts, newThreads, obj, opRoot, t, thread, threadData, threads; - threads = []; - newThreads = []; - newPosts = []; - for (k = 0, len1 = threadIDs.length; k < len1; k++) { - ID = threadIDs[k]; - try { - threadData = Index.liveThreadDict[ID]; - if ((thread = g.BOARD.threads.get(ID))) { - isStale = (thread.json !== threadData) && (JSON.stringify(thread.json) !== JSON.stringify(threadData)); - if (isStale) { - thread.setCount('post', threadData.replies + 1, threadData.bumplimit); - thread.setCount('file', threadData.images + !!threadData.ext, threadData.imagelimit); - thread.setStatus('Sticky', !!threadData.sticky); - thread.setStatus('Closed', !!threadData.closed); - } - if (thread.catalogView) { - $.rm(thread.catalogView.nodes.replies); - thread.catalogView.nodes.replies = null; - } - } else { - thread = new Thread(ID, g.BOARD); - newThreads.push(thread); - } - lastPost = threadData.last_replies && threadData.last_replies.length ? threadData.last_replies[threadData.last_replies.length - 1].no : ID; - if (lastPost > thread.lastPost) { - thread.lastPost = lastPost; - } - thread.json = threadData; - threads.push(thread); - if ((OP = thread.OP) && !OP.isFetchedQuote) { - OP.setCatalogOP(isCatalog); - thread.setPage(Math.floor(Index.threadPosition[ID] / Index.threadsNumPerPage) + 1); - } else { - obj = Index.parsedThreads[ID]; - opRoot = g.SITE.Build.post(obj); - OP = new Post(opRoot, thread, g.BOARD); - OP.filterResults = obj.filterResults; - newPosts.push(OP); - } - if (!(isCatalog && thread.nodes.root)) { - g.SITE.Build.thread(thread, threadData, withReplies); - } - } catch (error) { - err = error; - if (!errors) { - errors = []; - } - errors.push({ - message: "Parsing of Thread No." + thread + " failed. Thread will be skipped.", - error: err, - html: opRoot != null ? opRoot.outerHTML : void 0 - }); - } - } - if (errors) { - Main.handleErrors(errors); - } - if (withReplies) { - newPosts = newPosts.concat(Index.buildReplies(threads)); - } - Main.callbackNodes('Thread', newThreads); - Main.callbackNodes('Post', newPosts); - Index.updateHideLabel(); - $.event('IndexRefreshInternal', { - threadIDs: (function() { - var l, len2, results1; - results1 = []; - for (l = 0, len2 = threads.length; l < len2; l++) { - t = threads[l]; - results1.push(t.fullID); - } - return results1; - })(), - isCatalog: isCatalog - }); - return threads; - }, - buildReplies: function(threads) { - var data, err, errors, k, l, lastReplies, len1, len2, node, nodes, post, posts, thread; - posts = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - if (!(lastReplies = Index.liveThreadDict[thread.ID].last_replies)) { - continue; - } - nodes = []; - for (l = 0, len2 = lastReplies.length; l < len2; l++) { - data = lastReplies[l]; - if ((post = thread.posts.get(data.no)) && !post.isFetchedQuote) { - nodes.push(post.nodes.root); - continue; - } - nodes.push(node = g.SITE.Build.postFromObject(data, thread.board.ID)); - try { - posts.push(new Post(node, thread, thread.board)); - } catch (error) { - err = error; - if (!errors) { - errors = []; - } - errors.push({ - message: "Parsing of Post No." + data.no + " failed. Post will be skipped.", - error: err, - html: node != null ? node.outerHTML : void 0 - }); - } - } - $.add(thread.nodes.root, nodes); - } - if (errors) { - Main.handleErrors(errors); - } - return posts; - }, - buildCatalogViews: function(threads) { - var ID, catalogThreads, k, len1, page, root, thread; - catalogThreads = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - if (!(!thread.catalogView)) { - continue; - } - ID = thread.ID; - page = Math.floor(Index.threadPosition[ID] / Index.threadsNumPerPage) + 1; - root = g.SITE.Build.catalogThread(thread, Index.liveThreadDict[ID], page); - catalogThreads.push(new CatalogThread(root, thread)); - } - Main.callbackNodes('CatalogThread', catalogThreads); - }, - sizeCatalogViews: function(threads) { - var height, k, len1, ratio, ref, size, thread, thumb, width; - size = Conf['Index Size'] === 'small' ? 150 : 250; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - thumb = thread.catalogView.nodes.thumb; - ref = thumb.dataset, width = ref.width, height = ref.height; - if (!width) { - continue; - } - ratio = size / Math.max(width, height); - thumb.style.width = width * ratio + 'px'; - thumb.style.height = height * ratio + 'px'; - } - }, - buildCatalogReplies: function(thread) { - var data, k, lastReplies, len1, nodes, replies, reply; - nodes = thread.catalogView.nodes; - if (!(lastReplies = Index.liveThreadDict[thread.ID].last_replies)) { - return; - } - replies = []; - for (k = 0, len1 = lastReplies.length; k < len1; k++) { - data = lastReplies[k]; - if (Index.isHiddenReply(thread.ID, data)) { - continue; - } - reply = g.SITE.Build.catalogReply(thread, data); - RelativeDates.update($('time', reply)); - $.on($('.catalog-reply-preview', reply), 'mouseover', QuotePreview.mouseover); - replies.push(reply); - } - nodes.replies = $.el('div', { - className: 'catalog-replies' - }); - $.add(nodes.replies, replies); - $.add(thread.OP.nodes.post, nodes.replies); - }, - sort: function() { - var lastlong, lastlongD, liveThreadData, liveThreadIDs, repliesAvailable, sortType, thread, threadIDs, tmp_time; - liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; - if (!liveThreadData) { - return; - } - tmp_time = new Date().getTime() / 1000; - sortType = Index.currentSort.replace(/-rev$/, ''); - Index.sortedThreadIDs = (function() { - var k, len1; - switch (sortType) { - case 'lastreply': - case 'lastlong': - repliesAvailable = liveThreadData.some(function(thread) { - var ref; - return (ref = thread.last_replies) != null ? ref.length : void 0; - }); - lastlong = function(thread) { - var i, k, len, r, ref, ref1; - if (!repliesAvailable) { - return thread.last_modified; - } - ref = thread.last_replies || []; - for (i = k = ref.length - 1; k >= 0; i = k += -1) { - r = ref[i]; - if (Index.isHiddenReply(thread.no, r)) { - continue; - } - if (sortType === 'lastreply') { - return r; - } - len = r.com ? g.SITE.Build.parseComment(r.com).replace(/[^a-z]/ig, '').length : 0; - if (len >= Index.lastLongThresholds[+(!!r.ext)]) { - return r; - } - } - if (thread.omitted_posts && ((ref1 = thread.last_replies) != null ? ref1.length : void 0)) { - return thread.last_replies[0]; - } else { - return thread; - } - }; - lastlongD = $.dict(); - for (k = 0, len1 = liveThreadData.length; k < len1; k++) { - thread = liveThreadData[k]; - lastlongD[thread.no] = lastlong(thread).no; - } - return slice.call(liveThreadData).sort(function(a, b) { - return lastlongD[b.no] - lastlongD[a.no]; - }).map(function(post) { - return post.no; - }); - case 'bump': - return liveThreadIDs; - case 'birth': - return slice.call(liveThreadIDs).sort(function(a, b) { - return b - a; - }); - case 'replycount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.replies - a.replies; - }).map(function(post) { - return post.no; - }); - case 'filecount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.images - a.images; - }).map(function(post) { - return post.no; - }); - case 'activity': - return slice.call(liveThreadData).sort(function(a, b) { - return (tmp_time - a.time) / (a.replies + 1) - (tmp_time - b.time) / (b.replies + 1); - }).map(function(post) { - return post.no; - }); - default: - return liveThreadIDs; - } - })(); - if (/-rev$/.test(Index.currentSort)) { - Index.sortedThreadIDs = slice.call(Index.sortedThreadIDs).reverse(); - } - if (Index.search && (threadIDs = Index.querySearch(Index.search))) { - Index.sortedThreadIDs = threadIDs; - } - Index.sortOnTop(function(obj) { - return obj.isSticky; - }); - Index.sortOnTop(function(obj) { - return obj.isOnTop || Conf['Pin Watched Threads'] && ThreadWatcher.isWatchedRaw(obj.boardID, obj.threadID); - }); - if (Conf['Anchor Hidden Threads']) { - return Index.sortOnTop(function(obj) { - return !Index.isHidden(obj.threadID); - }); - } - }, - sortOnTop: function(match) { - var ID, bottomThreads, k, len1, ref, topThreads; - topThreads = []; - bottomThreads = []; - ref = Index.sortedThreadIDs; - for (k = 0, len1 = ref.length; k < len1; k++) { - ID = ref[k]; - (match(Index.parsedThreads[ID]) ? topThreads : bottomThreads).push(ID); - } - return Index.sortedThreadIDs = topThreads.concat(bottomThreads); - }, - buildIndex: function() { - var threadIDs; - if (!Index.liveThreadData) { - return; - } - switch (Conf['Index Mode']) { - case 'all pages': - threadIDs = Index.sortedThreadIDs; - break; - case 'catalog': - threadIDs = Index.sortedThreadIDs.filter(function(ID) { - return !Index.isHidden(ID) !== Index.showHiddenThreads; - }); - break; - default: - threadIDs = Index.threadsOnPage(Index.currentPage); - } - delete Index.pageNum; - $.rmAll(Index.root); - $.rmAll(Header.hover); - if (Index.loaded && Index.root.parentNode) { - $.event('PostsRemoved', null, Index.root); - } - if (Conf['Index Mode'] === 'catalog') { - Index.buildCatalog(threadIDs); - } else { - Index.buildStructure(threadIDs); - } - }, - threadsOnPage: function(pageNum) { - var nodesPerPage, offset; - nodesPerPage = Index.threadsNumPerPage; - offset = nodesPerPage * (pageNum - 1); - return Index.sortedThreadIDs.slice(offset, offset + nodesPerPage); - }, - buildStructure: function(threadIDs) { - var k, len1, nodes, thread, threads; - threads = Index.buildThreads(threadIDs, false, Conf['Show Replies']); - nodes = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - nodes.push(thread.nodes.root, $.el('hr')); - } - $.add(Index.root, nodes); - if (Index.root.parentNode) { - $.event('PostsInserted', null, Index.root); - } - Index.loaded = true; - }, - buildCatalog: function(threadIDs) { - var fn, i, n, node0; - i = 0; - n = threadIDs.length; - node0 = null; - fn = function() { - var j; - if (node0 && !node0.parentNode) { - return; - } - j = i > 0 && Index.root.parentNode ? n : i + 30; - node0 = Index.buildCatalogPart(threadIDs.slice(i, j))[0]; - i = j; - if (i < n) { - return $.queueTask(fn); - } else { - if (Index.root.parentNode) { - $.event('PostsInserted', null, Index.root); - } - return Index.loaded = true; - } - }; - fn(); - }, - buildCatalogPart: function(threadIDs) { - var k, len1, nodes, thread, threads; - threads = Index.buildThreads(threadIDs, true); - Index.buildCatalogViews(threads); - Index.sizeCatalogViews(threads); - nodes = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - thread.OP.setCatalogOP(true); - $.add(thread.catalogView.nodes.root, thread.OP.nodes.root); - nodes.push(thread.catalogView.nodes.root); - $.on(thread.catalogView.nodes.root, 'mouseenter', Index.cb.catalogReplies.bind(thread)); - $.on(thread.OP.nodes.root, 'mouseenter', Index.cb.hoverAdjust.bind(thread.OP.nodes)); - } - $.add(Index.root, nodes); - return nodes; - }, - clearSearch: function() { - Index.searchInput.value = ''; - Index.onSearchInput(); - return Index.searchInput.focus(); - }, - setupSearch: function() { - Index.searchInput.value = Index.search; - if (Index.search) { - return Index.searchInput.dataset.searching = 1; - } else { - return Index.searchInput.removeAttribute('data-searching'); - } - }, - onSearchInput: function() { - var search; - search = Index.searchInput.value.trim(); - if (search === Index.search) { - return; - } - Index.pushState({ - search: search, - replace: !!search === !!Index.search - }); - return Index.pageLoad(false); - }, - querySearch: function(query) { - var keywords, match, regexp; - if ((match = query.match(/^([\w+]+):\/(.*)\/(\w*)$/))) { - try { - regexp = RegExp(match[2], match[3]); - } catch (error) { - return []; - } - return Index.sortedThreadIDs.filter(function(ID) { - return regexp.test(Filter.values(match[1], Index.parsedThreads[ID]).join('\n')); - }); - } - if (!(keywords = query.toLowerCase().match(/\S+/g))) { - return; - } - return Index.sortedThreadIDs.filter(function(ID) { - return Index.searchMatch(Index.parsedThreads[ID], keywords); - }); - }, - searchMatch: function(obj, keywords) { - var file, info, k, key, keyword, l, len1, len2, ref, text; - info = obj.info, file = obj.file; - if (info.comment == null) { - info.comment = g.SITE.Build.parseComment(info.commentHTML.innerHTML); - } - text = []; - ref = ['comment', 'subject', 'name', 'tripcode']; - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - if (key in info) { - text.push(info[key]); - } - } - if (file) { - text.push(file.name); - } - text = text.join(' ').toLowerCase(); - for (l = 0, len2 = keywords.length; l < len2; l++) { - keyword = keywords[l]; - if (-1 === text.indexOf(keyword)) { - return false; - } - } - return true; - } - }; - - return Index; - -}).call(this); - -Polyfill = (function() { - var Polyfill; - - Polyfill = { - init: function() { - var base; - this.toBlob(); - $.global(this.toBlob); - (base = Element.prototype).matches || (base.matches = Element.prototype.mozMatchesSelector || Element.prototype.webkitMatchesSelector); - }, - toBlob: function() { - if (HTMLCanvasElement.prototype.toBlob) { - return; - } - HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { - var data, i, j, l, ref, ui8a, url; - url = this.toDataURL(type, encoderOptions); - data = atob(url.slice(url.indexOf(',') + 1)); - l = data.length; - ui8a = new Uint8Array(l); - for (i = j = 0, ref = l; j < ref; i = j += 1) { - ui8a[i] = data.charCodeAt(i); - } - return cb(new Blob([ui8a], { - type: type || 'image/png' - })); - }; - } - }; - - return Polyfill; - -}).call(this); - -Settings = (function() { - var Settings, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Settings = { - init: function() { - var add, link; - link = $.el('a', { - className: 'settings-link fa fa-wrench', - textContent: 'Settings', - title: '4chan X Settings', - href: 'javascript:;' - }); - $.on(link, 'click', Settings.open); - Header.addShortcut('settings', link, 820); - add = this.addSection; - add('Main', this.main); - add('Filter', this.filter); - add('Sauce', this.sauce); - add('Advanced', this.advanced); - add('Keybinds', this.keybinds); - $.on(d, 'AddSettingsSection', Settings.addSection); - $.on(d, 'OpenSettings', function(e) { - return Settings.open(e.detail); - }); - if (g.SITE.software === 'yotsuba' && Conf['Disable Native Extension']) { - if ($.hasStorage) { - return $.global(function() { - var settings; - try { - settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; - if (settings.disableAll) { - return; - } - settings.disableAll = true; - return localStorage.setItem('4chan-settings', JSON.stringify(settings)); - } catch (error) { - return Object.defineProperty(window, 'Config', { - value: { - disableAll: true - } - }); - } - }); - } else { - return $.global(function() { - return Object.defineProperty(window, 'Config', { - value: { - disableAll: true - } - }); - }); - } - } - }, - open: function(openSection) { - var dialog, j, len, link, links, ref, section, sectionToOpen; - if (Settings.dialog) { - return; - } - $.event('CloseMenu'); - Settings.dialog = dialog = $.el('div', { - id: 'overlay' - }, {innerHTML: ""}); - $.on($('.export', dialog), 'click', Settings["export"]); - $.on($('.import', dialog), 'click', Settings["import"]); - $.on($('.reset', dialog), 'click', Settings.reset); - $.on($('input', dialog), 'change', Settings.onImport); - links = []; - ref = Settings.sections; - for (j = 0, len = ref.length; j < len; j++) { - section = ref[j]; - link = $.el('a', { - className: "tab-" + section.hyphenatedTitle, - textContent: section.title, - href: 'javascript:;' - }); - $.on(link, 'click', Settings.openSection.bind(section)); - links.push(link, $.tn(' | ')); - if (section.title === openSection) { - sectionToOpen = link; - } - } - links.pop(); - $.add($('.sections-list', dialog), links); - if (openSection !== 'none') { - (sectionToOpen ? sectionToOpen : links[0]).click(); - } - $.on($('.close', dialog), 'click', Settings.close); - $.on(window, 'beforeunload', Settings.close); - $.on(dialog, 'click', Settings.close); - $.on(dialog.firstElementChild, 'click', function(e) { - return e.stopPropagation(); - }); - $.add(d.body, dialog); - return $.event('OpenSettings', null, dialog); - }, - close: function() { - var ref; - if (!Settings.dialog) { - return; - } - if ((ref = d.activeElement) != null) { - ref.blur(); - } - $.rm(Settings.dialog); - return delete Settings.dialog; - }, - sections: [], - addSection: function(title, open) { - var hyphenatedTitle, ref; - if (typeof title !== 'string') { - ref = title.detail, title = ref.title, open = ref.open; - } - hyphenatedTitle = title.toLowerCase().replace(/\s+/g, '-'); - return Settings.sections.push({ - title: title, - hyphenatedTitle: hyphenatedTitle, - open: open - }); - }, - openSection: function() { - var section, selected; - if (selected = $('.tab-selected', Settings.dialog)) { - $.rmClass(selected, 'tab-selected'); - } - $.addClass($(".tab-" + this.hyphenatedTitle, Settings.dialog), 'tab-selected'); - section = $('section', Settings.dialog); - $.rmAll(section); - section.className = "section-" + this.hyphenatedTitle; - this.open(section, g); - section.scrollTop = 0; - return $.event('OpenSettings', null, section); - }, - warnings: { - localStorage: function(cb) { - var why; - if ($.cantSync) { - why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; - return cb($.el('li', { - textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards." + (location.hostname.split('.')[1]) + ".org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." - })); - } - }, - ads: function(cb) { - return $.onExists(doc, '.adg-rects > .desktop', function(ad) { - return $.onExists(ad, 'iframe', function() { - var url; - url = Redirect.to('thread', { - boardID: 'qa', - threadID: 362590 - }); - return cb($.el('li', {innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan."})); - }); - }); - } - }, - main: function(section) { - var addCheckboxes, addWarning, button, div, fs, inputs, items, key, keyFS, obj, ref, ref1, warning, warnings; - warnings = $.el('fieldset', { - hidden: true - }, {innerHTML: "Warnings
    "}); - addWarning = function(item) { - $.add($('ul', warnings), item); - return warnings.hidden = false; - }; - ref = Settings.warnings; - for (key in ref) { - warning = ref[key]; - warning(addWarning); - } - $.add(section, warnings); - items = $.dict(); - inputs = $.dict(); - addCheckboxes = function(root, obj) { - var arr, container, containers, description, div, input, level, results; - containers = [root]; - results = []; - for (key in obj) { - arr = obj[key]; - if (!(arr instanceof Array)) { - continue; - } - description = arr[1]; - div = $.el('div', {innerHTML: ": " + E(description) + ""}); - div.dataset.name = key; - input = $('input', div); - $.on(input, 'change', $.cb.checked); - $.on(input, 'change', function() { - return this.parentNode.parentNode.dataset.checked = this.checked; - }); - items[key] = Conf[key]; - inputs[key] = input; - level = arr[2] || 0; - if (containers.length <= level) { - container = $.el('div', { - className: 'suboption-list' - }); - $.add(containers[containers.length - 1].lastElementChild, container); - containers[level] = container; - } else if (containers.length > level + 1) { - containers.splice(level + 1, containers.length - (level + 1)); - } - results.push($.add(containers[level], div)); - } - return results; - }; - ref1 = Config.main; - for (keyFS in ref1) { - obj = ref1[keyFS]; - fs = $.el('fieldset', {innerHTML: "" + E(keyFS) + ""}); - addCheckboxes(fs, obj); - if (keyFS === 'Posting and Captchas') { - $.add(fs, $.el('p', {innerHTML: "For more info on captcha options and issues, see the captcha FAQ."})); - } - $.add(section, fs); - } - addCheckboxes($('div[data-name="JSON Index"] > .suboption-list', section), Config.Index); - if ($.engine !== 'gecko') { - $('div[data-name="Remember QR Size"]', section).hidden = true; - } - if ($.perProtocolSettings || location.protocol !== 'https:') { - $('div[data-name="Redirect to HTTPS"]', section).hidden = true; - } - if ($.platform !== 'crx') { - $('div[data-name="Work around CORB Bug"]', section).hidden = true; - } - $.get(items, function(items) { - var val; - for (key in items) { - val = items[key]; - inputs[key].checked = val; - inputs[key].parentNode.parentNode.dataset.checked = val; - } - }); - div = $.el('div', {innerHTML: ": Clear manually-hidden threads and posts on all boards. Reload the page to apply."}); - button = $('button', div); - $.get({ - hiddenThreads: $.dict(), - hiddenPosts: $.dict() - }, function(arg) { - var ID, board, hiddenNum, hiddenPosts, hiddenThreads, ref2, ref3, ref4, ref5, site, thread; - hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; - hiddenNum = 0; - for (ID in hiddenThreads) { - site = hiddenThreads[ID]; - if (ID !== 'boards') { - ref2 = site.boards; - for (ID in ref2) { - board = ref2[ID]; - hiddenNum += Object.keys(board).length; - } - } - } - ref3 = hiddenThreads.boards; - for (ID in ref3) { - board = ref3[ID]; - hiddenNum += Object.keys(board).length; - } - for (ID in hiddenPosts) { - site = hiddenPosts[ID]; - if (ID !== 'boards') { - ref4 = site.boards; - for (ID in ref4) { - board = ref4[ID]; - for (ID in board) { - thread = board[ID]; - hiddenNum += Object.keys(thread).length; - } - } - } - } - ref5 = hiddenPosts.boards; - for (ID in ref5) { - board = ref5[ID]; - for (ID in board) { - thread = board[ID]; - hiddenNum += Object.keys(thread).length; - } - } - return button.textContent = "Hidden: " + hiddenNum; - }); - $.on(button, 'click', function() { - this.textContent = 'Hidden: 0'; - return $.get('hiddenThreads', $.dict(), function(arg) { - var boardID, hiddenThreads, ref2; - hiddenThreads = arg.hiddenThreads; - if ($.hasStorage && g.SITE.software === 'yotsuba') { - for (boardID in (ref2 = hiddenThreads['4chan.org']) != null ? ref2.boards : void 0) { - localStorage.removeItem("4chan-hide-t-" + boardID); - } - for (boardID in hiddenThreads.boards) { - localStorage.removeItem("4chan-hide-t-" + boardID); - } - } - return $["delete"](['hiddenThreads', 'hiddenPosts']); - }); - }); - return $.after($('input[name="Stubs"]', section).parentNode.parentNode, div); - }, - "export": function() { - var Conf2; - Conf2 = $.dict(); - $.extend(Conf2, Conf); - return $.get(Conf2, function(Conf2) { - delete Conf2['boardConfig']; - return Settings.downloadExport({ - version: g.VERSION, - date: Date.now(), - Conf: Conf2 - }); - }); - }, - downloadExport: function(data) { - var a, blob, p, url; - blob = new Blob([JSON.stringify(data, null, 2)], { - type: 'application/json' - }); - url = URL.createObjectURL(blob); - a = $.el('a', { - download: "4chan X v" + g.VERSION + "-" + data.date + ".json", - href: url - }); - p = $('.imp-exp-result', Settings.dialog); - $.rmAll(p); - $.add(p, a); - return a.click(); - }, - "import": function() { - return $('input[type=file]', this.parentNode).click(); - }, - onImport: function() { - var file, output, reader; - if (!(file = this.files[0])) { - return; - } - this.value = null; - 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 err; - try { - return Settings.loadSettings($.dict.json(e.target.result), function(err) { - if (err) { - return output.textContent = 'Import failed due to an error.'; - } else if (confirm('Import successful. Reload now?')) { - return window.location.reload(); - } - }); - } catch (error) { - err = error; - output.textContent = 'Import failed due to an error.'; - return c.error(err.stack); - } - }; - return reader.readAsText(file); - }, - convertFrom: { - loadletter: function(data) { - var base, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; - convertSettings = function(data, map) { - var newKey, prevKey; - for (prevKey in map) { - newKey = map[prevKey]; - if (newKey) { - data.Conf[newKey] = data.Conf[prevKey]; - } - delete data.Conf[prevKey]; - } - return data; - }; - data = convertSettings(data, { - 'Disable 4chan\'s extension': 'Disable Native Extension', - 'Comment Auto-Expansion': '', - 'Remove Slug': '', - 'Always HTTPS': 'Redirect to HTTPS', - 'Check for Updates': '', - 'Recursive Filtering': 'Recursive Hiding', - 'Reply Hiding': 'Reply Hiding Buttons', - 'Thread Hiding': 'Thread Hiding Buttons', - 'Show Stubs': 'Stubs', - 'Image Auto-Gif': 'Replace GIF', - 'Expand All WebM': 'Expand videos', - 'Reveal Spoilers': 'Reveal Spoiler Thumbnails', - 'Expand From Current': 'Expand from here', - 'Current Page': 'Page Count in Stats', - 'Current Page Position': '', - 'Alternative captcha': 'Use Recaptcha v1', - 'Alt index captcha': 'Use Recaptcha v1 on Index', - 'Auto Submit': 'Post on Captcha Completion', - 'Open Reply in New Tab': 'Open Post in New Tab', - 'Remember QR size': 'Remember QR Size', - 'Remember Subject': '', - 'Quote Inline': 'Quote Inlining', - 'Quote Preview': 'Quote Previewing', - 'Indicate OP quote': 'Mark OP Quotes', - 'Indicate You quote': 'Mark Quotes of You', - 'Indicate Cross-thread Quotes': 'Mark Cross-thread Quotes', - 'uniqueid': 'uniqueID', - 'mod': 'capcode', - 'email': '', - 'country': 'flag', - 'md5': 'MD5', - 'openEmptyQR': 'Open empty QR', - 'openQR': 'Open QR', - 'openOptions': 'Open settings', - 'close': 'Close', - 'spoiler': 'Spoiler tags', - 'sageru': 'Toggle sage', - 'code': 'Code tags', - 'sjis': 'SJIS tags', - 'submit': 'Submit QR', - 'watch': 'Watch', - 'update': 'Update', - 'unreadCountTo0': '', - 'expandAllImages': 'Expand images', - 'expandImage': 'Expand image', - 'zero': 'Front page', - 'nextPage': 'Next page', - 'previousPage': 'Previous page', - 'nextThread': 'Next thread', - 'previousThread': 'Previous thread', - 'expandThread': 'Expand thread', - 'openThreadTab': 'Open thread', - 'openThread': 'Open thread tab', - 'nextReply': 'Next reply', - 'previousReply': 'Previous reply', - 'hide': 'Hide', - 'Scrolling': 'Auto Scroll', - 'Verbose': '' - }); - if ('Always CDN' in data.Conf) { - data.Conf['fourchanImageHost'] = data.Conf['Always CDN'] ? 'i.4cdn.org' : ''; - delete data.Conf['Always CDN']; - } - data.Conf.sauces = data.Conf.sauces.replace(/\$\d/g, function(c) { - switch (c) { - case '$1': - return '%TURL'; - case '$2': - return '%URL'; - case '$3': - return '%MD5'; - case '$4': - return '%board'; - default: - return c; - } - }); - ref = Config.hotkeys; - for (key in ref) { - val = ref[key]; - if (key in data.Conf) { - data.Conf[key] = data.Conf[key].replace(/ctrl|alt|meta/g, function(s) { - return "" + (s[0].toUpperCase()) + s.slice(1); - }).replace(/(^|.+\+)[A-Z]$/g, function(s) { - return "Shift+" + s.slice(0, -1) + (s.slice(-1).toLowerCase()); - }); - } - } - if (data.WatchedThreads) { - data.Conf['watchedThreads'] = $.dict.clone({ - '4chan.org': { - boards: {} - } - }); - ref1 = data.WatchedThreads; - for (boardID in ref1) { - threads = ref1[boardID]; - for (threadID in threads) { - threadData = threads[threadID]; - ((base = data.Conf['watchedThreads']['4chan.org'].boards)[boardID] || (base[boardID] = $.dict()))[threadID] = { - excerpt: threadData.textContent - }; - } - } - } - return data; - } - }, - upgrade: function(data, version) { - var addCSS, addSauces, boardID, boards, changes, compareString, corrupted, db, hostname, j, k, key, l, lastChecked, len, len1, len2, len3, line, list, m, name, record, ref, ref1, ref10, ref11, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, rice, set, setD, siteProperties, software, type, uids, val, val2, value; - changes = $.dict(); - set = function(key, value) { - return data[key] = changes[key] = value; - }; - setD = function(key, value) { - if (data[key] == null) { - return set(key, value); - } - }; - addSauces = function(sauces) { - if (data['sauces'] != null) { - sauces = sauces.filter(function(s) { - return data['sauces'].indexOf(s.match(/[^#;\s]+|$/)[0]) < 0; - }); - if (sauces.length) { - return set('sauces', data['sauces'] + '\n\n' + sauces.join('\n')); - } - } - }; - addCSS = function(css) { - if (data['usercss'] == null) { - set('usercss', Config['usercss']); - } - if (data['usercss'].indexOf(css) < 0) { - return set('usercss', css + '\n\n' + data['usercss']); - } - }; - if ((corrupted = version[0] === '"')) { - try { - version = JSON.parse(version); - } catch (error) {} - } - compareString = version.replace(/\d+/g, function(x) { - return ('0000' + x).slice(-5); - }); - if (compareString < '00001.00013.00014.00008') { - for (key in data) { - val = data[key]; - if (!(typeof val === 'string' && typeof Conf[key] !== 'string' && (key !== 'Index Sort' && key !== 'Last Long Reply Thresholds 0' && key !== 'Last Long Reply Thresholds 1'))) { - continue; - } - corrupted = true; - break; - } - } - if (corrupted) { - for (key in data) { - val = data[key]; - if (typeof val === 'string') { - try { - val2 = JSON.parse(val); - set(key, val2); - } catch (error) {} - } - } - } - if (compareString < '00001.00011.00008.00000') { - if (data['Fixed Thread Watcher'] == null) { - set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); - } - if (data['Exempt Archives from Encryption'] == null) { - set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); - } - } - if (compareString < '00001.00011.00010.00001') { - if (data['selectedArchives'] != null) { - uids = { - "Moe": 0, - "4plebs Archive": 3, - "Nyafuu Archive": 4, - "Love is Over": 5, - "Rebecca Black Tech": 8, - "warosu": 10, - "fgts": 15, - "not4plebs": 22, - "DesuStorage": 23, - "fireden.net": 24, - "disabled": null - }; - ref2 = data['selectedArchives']; - for (boardID in ref2) { - record = ref2[boardID]; - for (type in record) { - name = record[type]; - if ($.hasOwn(uids, name)) { - record[type] = uids[name]; - } - } - } - set('selectedArchives', data['selectedArchives']); - } - } - if (compareString < '00001.00011.00016.00000') { - if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { - if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { - set('usercss', rice + '\n\n' + data['usercss']); - } - } - } - if (compareString < '00001.00011.00017.00000') { - ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; - for (j = 0, len = ref3.length; j < len; j++) { - key = ref3[j]; - if (data[key] == null) { - set(key, key === 'Persistent QR'); - } - } - } - if (compareString < '00001.00011.00017.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); - } - } - if (compareString < '00001.00011.00019.00003' && !Settings.dialog) { - $.queueTask(function() { - return Settings.warnings.ads(function(item) { - return new Notice('warning', slice.call(item.childNodes)); - }); - }); - } - if (compareString < '00001.00011.00020.00003') { - ref4 = { - 'Inline Cross-thread Quotes Only': false, - 'Pass Link': true - }; - for (key in ref4) { - value = ref4[key]; - if (data[key] == null) { - set(key, value); - } - } - } - if (compareString < '00001.00011.00021.00003') { - if (data['Remember Your Posts'] == null) { - set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); - } - } - if (compareString < '00001.00011.00022.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); - } - } - if (compareString < '00001.00011.00022.00002') { - if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { - set('Use Recaptcha v1 in Reports', true); - } - } - if (compareString < '00001.00011.00024.00000') { - if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { - set('JSON Index', data['JSON Navigation']); - } - } - if (compareString < '00001.00011.00026.00000') { - if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { - set('Edit Link', data['Oekaki Links']); - } - if (data['Inline Cross-thread Quotes Only'] == null) { - set('Inline Cross-thread Quotes Only', true); - } - } - if (compareString < '00001.00011.00030.00000') { - if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { - set('Thread Quotes', true); - } - } - if (compareString < '00001.00011.00032.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/3d\.iqdb\.org\//mg, '$1//3d.iqdb.org/')); - } - addSauces(['#https://desustorage.org/_/search/image/%sMD5/', '#https://boards.fireden.net/_/search/image/%sMD5/', '#https://foolz.fireden.net/_/search/image/%sMD5/', '#//www.gif-explode.com/%URL;types:gif']); - } - if (compareString < '00001.00011.00035.00000') { - addSauces(['https://whatanime.ga/?auto&url=%IMG;text:wait']); - } - if (compareString < '00001.00012.00000.00000') { - if (data['Exempt Archives from Encryption'] == null) { - set('Exempt Archives from Encryption', false); - } - if (data['Show New Thread Option in Threads'] == null) { - set('Show New Thread Option in Threads', false); - } - if (data['Show Name and Subject']) { - addCSS('#qr .persona .field {display: block !important;}'); - } - if (data['QR Shortcut'] === false) { - addCSS('#shortcut-qr {display: none;}'); - } - if (data['Bottom QR Link'] === false) { - addCSS('.qr-link-container-bottom {display: none;}'); - } - } - if (compareString < '00001.00012.00000.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)https:\/\/(?:desustorage|cuckchan)\.org\//mg, '$1https://desuarchive.org/')); - } - } - if (compareString < '00001.00012.00001.00000') { - if ((data['Persistent Thread Watcher'] == null) && (data['Toggleable Thread Watcher'] != null)) { - set('Persistent Thread Watcher', !data['Toggleable Thread Watcher']); - } - } - if (compareString < '00001.00012.00003.00000') { - ref6 = ['Image Hover in Catalog', 'Auto Watch', 'Auto Watch Reply']; - for (k = 0, len1 = ref6.length; k < len1; k++) { - key = ref6[k]; - setD(key, false); - } - } - if (compareString < '00001.00013.00001.00002') { - addSauces(['#//www.bing.com/images/search?q=imgurl:%IMG&view=detailv2&iss=sbi#enterInsights']); - } - if (compareString < '00001.00013.00005.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/regex\.info\/exif\.cgi/mg, '$1http://exif.regex.info/exif.cgi')); - } - addSauces(Config['sauces'].match(/# Known filename formats:(?:\n.+)*|$/)[0].split('\n')); - } - if (compareString < '00001.00013.00007.00002') { - setD('Require OP Quote Link', true); - } - if (compareString < '00001.00013.00008.00000') { - setD('Download Link', true); - } - if (compareString < '00001.00013.00009.00003') { - if (data['jsWhitelist'] != null) { - list = data['jsWhitelist'].split('\n'); - if (indexOf.call(list, 'https://cdnjs.cloudflare.com') < 0 && indexOf.call(list, 'https://cdn.mathjax.org') >= 0) { - set('jsWhitelist', data['jsWhitelist'] + '\n\nhttps://cdnjs.cloudflare.com'); - } - } - } - if (compareString < '00001.00014.00000.00006') { - if (data['siteSoftware'] != null) { - set('siteSoftware', data['siteSoftware'] + '\n4cdn.org yotsuba'); - } - } - if (compareString < '00001.00014.00003.00002') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)https:\/\/whatanime\.ga\//mg, '$1https://trace.moe/')); - } - } - if (compareString < '00001.00014.00004.00004') { - if ((data['siteSoftware'] != null) && !/^4channel\.org yotsuba$/m.test(data['siteSoftware'])) { - set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba'); - } - } - if (compareString < '00001.00014.00005.00000') { - ref7 = DataBoard.keys; - for (l = 0, len2 = ref7.length; l < len2; l++) { - db = ref7[l]; - if ((ref8 = data[db]) != null ? ref8.boards : void 0) { - ref9 = data[db], boards = ref9.boards, lastChecked = ref9.lastChecked; - data[db]['4chan.org'] = { - boards: boards, - lastChecked: lastChecked - }; - delete data[db].boards; - delete data[db].lastChecked; - set(db, data[db]); - } - } - if ((data['siteSoftware'] != null) && (data['siteProperties'] == null)) { - siteProperties = $.dict(); - ref10 = data['siteSoftware'].split('\n'); - for (m = 0, len3 = ref10.length; m < len3; m++) { - line = ref10[m]; - ref11 = line.split(' '), hostname = ref11[0], software = ref11[1]; - siteProperties[hostname] = { - software: software - }; - } - set('siteProperties', siteProperties); - } - } - if (compareString < '00001.00014.00006.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/\/\/%\$1\.deviantart\.com\/gallery\/#\/d%\$2;regexp:\/\^\\w\+_by_\(\\w\+\)-d\(\[\\da-z\]\+\)\//g, '//www.deviantart.com/gallery/#/d%$1%$2;regexp:/^\\w+_by_\\w+[_-]d([\\da-z]{6})\\b|^d([\\da-z]{6})-[\\da-z]{8}-/')); - } - } - if (compareString < '00001.00014.00008.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/https:\/\/www\.yandex\.com\/images\/search/g, 'https://yandex.com/images/search')); - } - } - if (compareString < '00001.00014.00009.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)(?:http:)?\/\/(www\.pixiv\.net|www\.deviantart\.com|imgur\.com|flickr\.com)\//mg, '$1https://$2/')); - set('sauces', data['sauces'].replace(/https:\/\/yandex\.com\/images\/search\?rpt=imageview&img_url=%IMG/g, 'https://yandex.com/images/search?rpt=imageview&url=%IMG')); - } - } - if (compareString < '00001.00014.00009.00001') { - if ((data['Use Faster Image Host'] != null) && (data['fourchanImageHost'] == null)) { - set('fourchanImageHost', (data['Use Faster Image Host'] ? 'i.4cdn.org' : '')); - } - } - if (compareString < '00001.00014.00010.00001') { - if (data['Filter in Native Catalog'] == null) { - set('Filter in Native Catalog', false); - } - } - if (compareString < '00001.00014.00012.00008') { - if (data['boardnav'] == null) { - set('boardnav', "[ toggle-all ]\na-replace\nc-replace\ng-replace\nk-replace\nv-replace\nvg-replace\nvr-replace\nck-replace\nco-replace\nfit-replace\njp-replace\nmu-replace\nsp-replace\ntv-replace\nvp-replace\n[external-text:\"FAQ\",\"https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions\"]"); - } - } - if (compareString < '00001.00014.00016.00001') { - if (data['archiveLists'] != null) { - set('archiveLists', data['archiveLists'].replace('https://mayhemydg.github.io/archives.json/archives.json', 'https://nstepien.github.io/archives.json/archives.json')); - } - } - if (compareString < '00001.00014.00016.00007') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/https:\/\/www\.deviantart\.com\/gallery\/#\/d%\$1%\$2;regexp:\/\^\\w\+_by_\\w\+\[_-\]d\(\[\\da-z\]\{6\}\)\\b\|\^d\(\[\\da-z\]\{6\}\)-\[\\da-z\]\{8\}-\//g, 'javascript:void(open("https://www.deviantart.com/"+%$1.replace(/_/g,"-")+"/art/"+parseInt(%$2,36)));regexp:/^\\w+_by_(\\w+)[_-]d([\\da-z]{6})\\b/').replace(/\/\/imgops\.com\/%URL/g, '//imgops.com/start?url=%URL')); - } - } - if (compareString < '00001.00014.00017.00002') { - if (data['jsWhitelist'] != null) { - set('jsWhitelist', data['jsWhitelist'] + '\n\nhttps://hcaptcha.com\nhttps://*.hcaptcha.com'); - } - } - if (compareString < '00001.00014.00020.00004') { - if (data['archiveLists'] != null) { - set('archiveLists', data['archiveLists'].replace('https://nstepien.github.io/archives.json/archives.json', 'https://4chenz.github.io/archives.json/archives.json')); - } - } - if (compareString < '00001.00014.00022.00003') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(IMG|T?URL)&safe=off(?=$|;)/mg, 'https://www.google.com/searchbyimage?sbisrc=4chanx&image_url=%$1&safe=off')); - if (compareString === '00001.00014.00022.00002' && !/\bsbisrc=/.test(data['sauces'])) { - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/lens\.google\.com\/uploadbyurl\?url=%(IMG|T?URL)(?=$|;)/m, 'https://www.google.com/searchbyimage?sbisrc=4chanx&image_url=%$1&safe=off')); - } - } - addSauces(['#https://lens.google.com/uploadbyurl?url=%IMG;text:lens']); - } - return changes; - }, - loadSettings: function(data, cb) { - if (data.version.split('.')[0] === '2') { - data = Settings.convertFrom.loadletter(data); - } else if (data.version !== g.VERSION) { - Settings.upgrade(data.Conf, data.version); - } - return $.clear(function(err) { - if (err) { - return cb(err); - } - return $.set(data.Conf, cb); - }); - }, - reset: function() { - if (confirm('Your current settings will be entirely wiped, are you sure?')) { - return $.clear(function(err) { - if (err) { - return $('.imp-exp-result').textContent = 'Import failed due to an error.'; - } else if (confirm('Reset successful. Reload now?')) { - return window.location.reload(); - } - }); - } - }, - filter: function(section) { - var select; - $.extend(section, {innerHTML: "
    "}); - select = $('select', section); - $.on(select, 'change', Settings.selectFilter); - return Settings.selectFilter.call(select); - }, - selectFilter: function() { - var div, filterTypes, name, ta; - div = this.nextElementSibling; - if ((name = this.value) !== 'guide') { - if (!$.hasOwn(Config.filter, name)) { - return; - } - $.rmAll(div); - ta = $.el('textarea', { - name: name, - className: 'field', - spellcheck: false - }); - $.on(ta, 'change', $.cb.value); - $.get(name, Conf[name], function(item) { - ta.value = item[name]; - return $.add(div, ta); - }); - return; - } - filterTypes = Object.keys(Config.filter).filter(function(x) { - return x !== 'general'; - }).map(function(x, i) { - return {innerHTML: ((i) ? "," : "") + "" + E(x)}; - }); - $.extend(div, {innerHTML: "
    Filter is disabled.

    Use regular expressions, one per line.
    Lines starting with a # will be ignored.
    For example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
    MD5 and Unique ID filtering use exact string matching, not regular expressions.

      You can use these settings with each regular expression, separate them with semicolons:
    • Per boards, separate them with commas. It is global if not specified. Use sfw and nsfw to reference all worksafe or not-worksafe boards.
      For example: boards:a,jp;.
      To specify boards on a particular site, put the beginning of the domain and a slash character before the list.
      Any initial www. should not be included, and all 4chan domains are considered 4chan.org.
      For example: boards:4:a,jp,sama:a,z;.
      An asterisk can be used to specify all boards on a site.
      For example: boards:4:*;.
    • Select boards to be excluded from the filter. The syntax is the same as for the boards: option above.
      For example: exclude:vg,v;.
    • Filter OPs only along with their threads (`only`) or replies only (`no`).
      For example: op:only; or op:no;.
    • Filter only posts with files (`only`) or only posts without files (`no`).
      For example: file:only; or file:no;.
    • Overrule the `Show Stubs` setting if specified: create a stub (`yes`) or not (`no`).
      For example: stub:yes; or stub:no;.
    • Highlight instead of hiding. You can specify a class name to use with a userstyle.
      For example: highlight; or highlight:wallpaper;.
    • Highlighted OPs will have their threads put on top of the board index by default.
      For example: top:yes; or top:no;.
    • Show a desktop notification instead of hiding.
      For example: notify;.
    • Filters in the \"General\" section apply to multiple fields, by default subject,name,filename,comment.
      The fields can be specified with the type option, separated by commas.
      For example: type:" + E.cat(filterTypes) + ";.
      Types can also be combined with a + sign; this indicates the filter applies to the given fields joined by newlines.
      For example: type:filename+filesize+dimensions;.
    "}); - return $('.warning', div).hidden = Conf['Filter']; - }, - sauce: function(section) { - var ta; - $.extend(section, {innerHTML: "
    Sauce is disabled.
    These parameters will be replaced by their corresponding values in the URL and displayed text:
    • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
    • %URL: Full image URL.
    • %TURL: Thumbnail URL.
    • %name: Original file name.
    • %board: Current board.
    • %MD5: MD5 hash in base64.
    • %sMD5: MD5 hash in base64 using - and _.
    • %hMD5: MD5 hash in hexadecimal.
    • %$0: Matched regular expression within the filename.
    • %$1, %$2, %$3, ... : Subexpressions within the matched regular expression.
    • %%, %semi: Literal % and ;.
    Lines starting with a # will be ignored.
    You can specify a display text by appending ;text:[text] to the URL.
    You can specify the applicable boards/sites by appending ;boards:[board1],[board2]. See the Filter guide for details.
    You can specify the applicable file types by appending ;types:[extension1],[extension2].
    You can specify a regular expression the filename must match by appending ;regexp:[regular expression].
    "}); - $('.warning', section).hidden = Conf['Sauce']; - ta = $('textarea', section); - $.get('sauces', Conf['sauces'], function(item) { - ta.value = item['sauces']; - return ta.hidden = false; - }); - return $.on(ta, 'change', $.cb.value); - }, - advanced: function(section) { - var applyCSS, boardSelect, customCSS, event, input, inputs, interval, items, itemsArchive, j, k, l, len, len1, len2, len3, listImageHost, m, name, ref, ref1, ref2, ref3, ref4, table, textContent, updateArchives, warning; - $.extend(section, {innerHTML: "
    Archives
    404 Redirect is disabled.
    Thread redirectionPost fetchingFile redirection

    Archive Lists: Each line below should be an archive list in this format or a URL to load an archive list from.
    Archive properties can be overriden by another item with the same uid (or if absent, its name).
    Last updated:
    External Catalog
    External Catalog is disabled. This will be used only as a fallback.
    URLs of external catalog sites, where %board is to be replaced by the board name.
    Each URL should be followed by ;boards: and optionally ;exclude: and a list of supported/excluded boards in the format explained in the Filter guide.
    Override 4chan Image Host
    Change 4chan image links to this domain. Leave blank for no change.
    Captcha Language
    Choose from list of language codes. Leave blank to autoselect.
    Custom Board Navigation
    New lines will be converted into spaces.

    In the following examples for /g/, g can be changed to a different board ID (a, b, etc...), the current board (current), or the Twitter link (@).
    Board link: g
    Archive link: g-archive
    Internal archive link: g-expired
    Title link: g-title
    Board link (Replace with title when on that board): g-replace
    Full text link: g-full
    Custom text link: g-text:"Install Gentoo"
    Index-only link: g-index
    Catalog-only link: g-catalog
    Index mode: g-mode:"infinite scrolling"
    Index sort: g-sort:"creation date rev"
    External link: external-text:"Google","http://www.google.com"
    Open in new tab: g-nt
    Combinations are possible: g-index-text:"Technology Index"
    Full board list toggle: toggle-all

    [ toggle-all ] [current-title] [g-title / a-title / jp-title] [x / wsg / h] [t-text:"Piracy"]
    will give you
    [ + ] [Technology] [Technology / Anime & Manga / Otaku Culture] [x / wsg / h] [Piracy]
    if you are on /g/.
    Time Formatting is disabled.
    :
    Day: %a, %A, %d, %e
    Month: %m, %b, %B
    Year: %y, %Y
    Hour: %k, %H, %l, %I, %p, %P
    Minute: %M
    Second: %S
    Literal %: %%
    Quote Backlinks formatting is disabled.
    :
    Default pasted content filename
    .png
    File Info Formatting is disabled.
    :
    Link: %l (truncated), %L (untruncated), %T (4chan filename)
    Filename: %n (truncated), %N (untruncated), %t (4chan filename)
    Download button: %d
    Quick filter MD5: %f
    Spoiler indicator: %p
    Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
    Resolution: %r (Displays 'PDF' for PDF files)
    Tag: %g
    Literal %: %%
    Quick Reply Personas

    One item per line.
    Items will be added in the relevant input's auto-completion list.
    Password items will always be used, since there is no password input.
    Lines starting with a # will be ignored.

      You can use these settings with each item, separate them with semicolons:
    • Possible items are: name, options (or equivalently email), subject and password.
    • Wrap values of items with quotes, like this: options:"sage".
    • Force values as defaults with the always keyword, for example: options:"sage";always.
    • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
    Unread Favicon is disabled.
    Thread Updater is disabled.
    Interval: seconds
    Custom Cooldown Time
    Seconds:
    For more information about customizing 4chan X's CSS, see the styling guide.
    Javascript Whitelist
    Sources from which Javascript is allowed to be loaded by Content Security Policy.
    Lines starting with a # will be ignored.
    Known Banners
    List of known banners, used for click-to-change feature.
    "}); - ref = $$('.warning', section); - for (j = 0, len = ref.length; j < len; j++) { - warning = ref[j]; - warning.hidden = Conf[warning.dataset.feature]; - } - inputs = $.dict(); - ref1 = $$('[name]', section); - for (k = 0, len1 = ref1.length; k < len1; k++) { - input = ref1[k]; - inputs[input.name] = input; - } - $.on(inputs['archiveLists'], 'change', function() { - $.set('lastarchivecheck', 0); - Conf['lastarchivecheck'] = 0; - return $.id('lastarchivecheck').textContent = 'never'; - }); - items = $.dict(); - for (name in inputs) { - input = inputs[name]; - if (!(name !== 'Interval' && name !== 'Custom CSS')) { - continue; - } - items[name] = Conf[name]; - event = (input.nodeName === 'SELECT' || ((ref2 = input.type) === 'checkbox' || ref2 === 'radio') || (input.nodeName === 'TEXTAREA' && !(name in Settings))) ? 'change' : 'input'; - $.on(input, event, $.cb[input.type === 'checkbox' ? 'checked' : 'value']); - if (name in Settings) { - $.on(input, event, Settings[name]); - } - } - $.get(items, function(items) { - var key, val; - for (key in items) { - val = items[key]; - input = inputs[key]; - input[input.type === 'checkbox' ? 'checked' : 'value'] = val; - input.hidden = false; - if (key in Settings) { - Settings[key].call(input); - } - } - }); - listImageHost = $.id('list-fourchanImageHost'); - ref3 = ImageHost.suggestions; - for (l = 0, len2 = ref3.length; l < len2; l++) { - textContent = ref3[l]; - $.add(listImageHost, $.el('option', { - textContent: textContent - })); - } - interval = inputs['Interval']; - customCSS = inputs['Custom CSS']; - applyCSS = $('#apply-css', section); - interval.value = Conf['Interval']; - customCSS.checked = Conf['Custom CSS']; - inputs['usercss'].disabled = !Conf['Custom CSS']; - applyCSS.disabled = !Conf['Custom CSS']; - $.on(interval, 'change', ThreadUpdater.cb.interval); - $.on(customCSS, 'change', Settings.togglecss); - $.on(applyCSS, 'click', function() { - return CustomCSS.update(); - }); - itemsArchive = $.dict(); - ref4 = ['archives', 'selectedArchives', 'lastarchivecheck']; - for (m = 0, len3 = ref4.length; m < len3; m++) { - name = ref4[m]; - itemsArchive[name] = Conf[name]; - } - $.get(itemsArchive, function(itemsArchive) { - $.extend(Conf, itemsArchive); - Redirect.selectArchives(); - return Settings.addArchiveTable(section); - }); - boardSelect = $('#archive-board-select', section); - table = $('#archive-table', section); - updateArchives = $('#update-archives', section); - $.on(boardSelect, 'change', function() { - $('tbody > :not([hidden])', table).hidden = true; - return $("tbody > ." + this.value, table).hidden = false; - }); - return $.on(updateArchives, 'click', function() { - return Redirect.update(function() { - return Settings.addArchiveTable(section); - }); - }); - }, - addArchiveTable: function(section) { - var archBoards, archive, boardID, boardOptions, boardSelect, boards, data, files, id, item, j, k, l, len, len1, len2, len3, m, name, o, ref, ref1, ref2, ref3, ref4, row, rows, select, software, table, tbody, type, uid; - $('#lastarchivecheck', section).textContent = Conf['lastarchivecheck'] === 0 ? 'never' : new Date(Conf['lastarchivecheck']).toLocaleString(); - boardSelect = $('#archive-board-select', section); - table = $('#archive-table', section); - tbody = $('tbody', section); - $.rmAll(boardSelect); - $.rmAll(tbody); - archBoards = $.dict(); - ref = Conf['archives']; - for (j = 0, len = ref.length; j < len; j++) { - ref1 = ref[j], uid = ref1.uid, name = ref1.name, boards = ref1.boards, files = ref1.files, software = ref1.software; - if (software !== 'fuuka' && software !== 'foolfuuka') { - continue; - } - for (k = 0, len1 = boards.length; k < len1; k++) { - boardID = boards[k]; - o = archBoards[boardID] || (archBoards[boardID] = { - thread: [], - post: [], - file: [] - }); - archive = [uid != null ? uid : name, name]; - o.thread.push(archive); - if (software === 'foolfuuka') { - o.post.push(archive); - } - if (indexOf.call(files, boardID) >= 0) { - o.file.push(archive); - } - } - } - rows = []; - boardOptions = []; - ref2 = Object.keys(archBoards).sort(); - for (l = 0, len2 = ref2.length; l < len2; l++) { - boardID = ref2[l]; - row = $.el('tr', { - className: "board-" + boardID - }); - row.hidden = boardID !== g.BOARD.ID; - boardOptions.push($.el('option', { - textContent: "/" + boardID + "/", - value: "board-" + boardID, - selected: boardID === g.BOARD.ID - })); - o = archBoards[boardID]; - ref3 = ['thread', 'post', 'file']; - for (m = 0, len3 = ref3.length; m < len3; m++) { - item = ref3[m]; - $.add(row, Settings.addArchiveCell(boardID, o, item)); - } - rows.push(row); - } - if (rows.length === 0) { - boardSelect.hidden = table.hidden = true; - return; - } - boardSelect.hidden = table.hidden = false; - if (!(g.BOARD.ID in archBoards)) { - rows[0].hidden = false; - } - $.add(boardSelect, boardOptions); - $.add(tbody, rows); - ref4 = Conf['selectedArchives']; - for (boardID in ref4) { - data = ref4[boardID]; - for (type in data) { - id = data[type]; - if ((select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", tbody))) { - select.value = JSON.stringify(id); - if (!select.value) { - select.value = select.firstChild.value; - } - } - } - } - }, - addArchiveCell: function(boardID, data, type) { - var archive, i, length, options, select, td; - length = data[type].length; - td = $.el('td', { - className: 'archive-cell' - }); - if (!length) { - td.textContent = '--'; - return td; - } - options = []; - i = 0; - while (i < length) { - archive = data[type][i++]; - options.push($.el('option', { - value: JSON.stringify(archive[0]), - textContent: archive[1] - })); - } - $.extend(td, {innerHTML: ""}); - select = td.firstElementChild; - if (!(select.disabled = length === 1)) { - select.setAttribute('data-boardid', boardID); - select.setAttribute('data-type', type); - $.on(select, 'change', Settings.saveSelectedArchive); - } - $.add(select, options); - return td; - }, - saveSelectedArchive: function() { - return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { - return function(arg) { - var name1, selectedArchives; - selectedArchives = arg.selectedArchives; - (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = $.dict()))[_this.dataset.type] = JSON.parse(_this.value); - $.set('selectedArchives', selectedArchives); - Conf['selectedArchives'] = selectedArchives; - return Redirect.selectArchives(); - }; - })(this)); - }, - boardnav: function() { - return Header.generateBoardList(this.value); - }, - time: function() { - return this.nextElementSibling.textContent = Time.format(this.value, new Date()); - }, - timeLocale: function() { - return Settings.time.call($('[name=time]', Settings.dialog)); - }, - backlink: function() { - return this.nextElementSibling.textContent = this.value.replace(/%(?:id|%)/g, function(x) { - return { - '%id': '123456789', - '%%': '%' - }[x]; - }); - }, - fileInfo: function() { - var data; - data = { - isReply: true, - file: { - url: "//" + (ImageHost.host()) + "/g/1334437723720.jpg", - name: 'd9bb2efc98dd0df141a94399ff5880b7.jpg', - size: '276 KB', - sizeInBytes: 276 * 1024, - dimensions: '1280x720', - isImage: true, - isVideo: false, - isSpoiler: true, - tag: 'Loop' - } - }; - return FileInfo.format(this.value, data, this.nextElementSibling); - }, - favicon: function() { - var f, i, icon, img, j, len, ref; - Favicon["switch"](); - if (g.VIEW === 'thread' && Conf['Unread Favicon']) { - Unread.update(); - } - img = this.nextElementSibling.children; - f = Favicon; - ref = [f.SFW, f.unreadSFW, f.unreadSFWY, f.NSFW, f.unreadNSFW, f.unreadNSFWY, f.dead, f.unreadDead, f.unreadDeadY]; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - icon = ref[i]; - if (!img[i]) { - $.add(this.nextElementSibling, $.el('img')); - } - img[i].src = icon; - } - }, - togglecss: function() { - if ($('textarea[name=usercss]', $.x('ancestor::fieldset[1]', this)).disabled = $.id('apply-css').disabled = !this.checked) { - CustomCSS.rmStyle(); - } else { - CustomCSS.addStyle(); - } - return $.cb.checked.call(this); - }, - keybinds: function(section) { - var arr, input, inputs, items, key, ref, tbody, tr; - $.extend(section, {innerHTML: "
    Keybinds are disabled.
    Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
    Press Backspace to disable a keybind.
    ActionsKeybinds
    "}); - $('.warning', section).hidden = Conf['Keybinds']; - tbody = $('tbody', section); - items = $.dict(); - inputs = $.dict(); - ref = Config.hotkeys; - for (key in ref) { - arr = ref[key]; - tr = $.el('tr', {innerHTML: "" + E(arr[1]) + ""}); - input = $('input', tr); - input.name = key; - input.spellcheck = false; - items[key] = Conf[key]; - inputs[key] = input; - $.on(input, 'keydown', Settings.keybind); - $.add(tbody, tr); - } - return $.get(items, function(items) { - var val; - for (key in items) { - val = items[key]; - inputs[key].value = val; - } - }); - }, - 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); - } - }; - - return Settings; - -}).call(this); - -Test = (function() { - return Test; - -}).call(this); - -UI = (function() { - var Menu, UI, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, - slice = [].slice; - - dialog = function(id, properties) { - var child, el, i, len, move, ref; - el = $.el('div', { - className: 'dialog', - id: id - }); - $.extend(el, properties); - el.style.cssText = Conf[id + ".position"]; - move = $('.move', el); - $.on(move, 'touchstart mousedown', dragstart); - ref = move.children; - for (i = 0, len = ref.length; i < len; i++) { - child = ref[i]; - if (!child.tagName) { - continue; - } - $.on(child, 'touchstart mousedown', function(e) { - return e.stopPropagation(); - }); - } - return el; - }; - - Menu = (function() { - var currentMenu, lastToggledButton; - - currentMenu = null; - - lastToggledButton = null; - - function Menu(type) { - this.type = type; - this.addEntry = bind(this.addEntry, this); - this.onFocus = bind(this.onFocus, this); - this.keybinds = bind(this.keybinds, this); - this.close = bind(this.close, this); - this.setPosition = bind(this.setPosition, this); - $.on(d, 'AddMenuEntry', (function(_this) { - return function(arg) { - var detail; - detail = arg.detail; - if (detail.type !== _this.type) { - return; - } - delete detail.open; - return _this.addEntry(detail); - }; - })(this)); - this.entries = []; - } - - Menu.prototype.makeMenu = function() { - var menu; - menu = $.el('div', { - className: 'dialog', - id: 'menu', - tabIndex: 0 - }); - menu.dataset.type = this.type; - $.on(menu, 'click', function(e) { - return e.stopPropagation(); - }); - $.on(menu, 'keydown', this.keybinds); - return menu; - }; - - Menu.prototype.toggle = function(e, button, data) { - var previousButton; - e.preventDefault(); - e.stopPropagation(); - if (currentMenu) { - previousButton = lastToggledButton; - currentMenu.close(); - if (previousButton === button) { - return; - } - } - if (!this.entries.length) { - return; - } - return this.open(button, data); - }; - - Menu.prototype.open = function(button, data) { - var entry, i, len, menu, ref; - menu = this.menu = this.makeMenu(); - currentMenu = this; - lastToggledButton = button; - this.entries.sort(function(first, second) { - return first.order - second.order; - }); - ref = this.entries; - for (i = 0, len = ref.length; i < len; i++) { - entry = ref[i]; - this.insertEntry(entry, menu, data); - } - $.addClass(lastToggledButton, 'active'); - $.on(d, 'click CloseMenu', this.close); - $.on(d, 'scroll', this.setPosition); - $.on(window, 'resize', this.setPosition); - $.after(button, menu); - this.setPosition(); - entry = $('.entry', menu); - this.focus(entry); - return menu.focus(); - }; - - Menu.prototype.setPosition = function() { - var bLeft, bRect, bTop, bottom, cHeight, cWidth, left, mRect, ref, ref1, right, top; - mRect = this.menu.getBoundingClientRect(); - bRect = lastToggledButton.getBoundingClientRect(); - bTop = window.scrollY + bRect.top; - bLeft = window.scrollX + bRect.left; - cHeight = doc.clientHeight; - cWidth = doc.clientWidth; - ref = bRect.top + bRect.height + mRect.height < cHeight ? [bRect.bottom + "px", ''] : ['', (cHeight - bRect.top) + "px"], top = ref[0], bottom = ref[1]; - ref1 = bRect.left + mRect.width < cWidth ? [bRect.left + "px", ''] : ['', (cWidth - bRect.right) + "px"], left = ref1[0], right = ref1[1]; - $.extend(this.menu.style, { - top: top, - right: right, - bottom: bottom, - left: left - }); - return this.menu.classList.toggle('left', right); - }; - - Menu.prototype.insertEntry = function(entry, parent, data) { - var err, i, len, ref, subEntry, submenu; - if (typeof entry.open === 'function') { - try { - if (!entry.open(data)) { - return; - } - } catch (error) { - err = error; - Main.handleErrors({ - message: "Error in building the " + this.type + " menu.", - error: err - }); - return; - } - } - $.add(parent, entry.el); - if (!entry.subEntries) { - return; - } - if (submenu = $('.submenu', entry.el)) { - $.rm(submenu); - } - submenu = $.el('div', { - className: 'dialog submenu' - }); - ref = entry.subEntries; - for (i = 0, len = ref.length; i < len; i++) { - subEntry = ref[i]; - this.insertEntry(subEntry, submenu, data); - } - $.add(entry.el, submenu); - }; - - Menu.prototype.close = function() { - $.rm(this.menu); - delete this.menu; - $.rmClass(lastToggledButton, 'active'); - currentMenu = null; - lastToggledButton = null; - $.off(d, 'click scroll CloseMenu', this.close); - $.off(d, 'scroll', this.setPosition); - return $.off(window, 'resize', this.setPosition); - }; - - Menu.prototype.findNextEntry = function(entry, direction) { - var entries; - entries = slice.call(entry.parentNode.children); - entries.sort(function(first, second) { - return first.style.order - second.style.order; - }); - return entries[entries.indexOf(entry) + direction]; - }; - - Menu.prototype.keybinds = function(e) { - var entry, next, nextPrev, subEntry, submenu; - entry = $('.focused', this.menu); - while (subEntry = $('.focused', entry)) { - entry = subEntry; - } - switch (e.keyCode) { - case 27: - lastToggledButton.focus(); - this.close(); - break; - case 13: - case 32: - entry.click(); - break; - case 38: - if (next = this.findNextEntry(entry, -1)) { - this.focus(next); - } - break; - case 40: - if (next = this.findNextEntry(entry, +1)) { - this.focus(next); - } - break; - case 39: - if ((submenu = $('.submenu', entry)) && (next = submenu.firstElementChild)) { - while (nextPrev = this.findNextEntry(next, -1)) { - next = nextPrev; - } - this.focus(next); - } - break; - case 37: - if (next = $.x('parent::*[contains(@class,"submenu")]/parent::*', entry)) { - this.focus(next); - } - break; - default: - return; - } - e.preventDefault(); - return e.stopPropagation(); - }; - - Menu.prototype.onFocus = function(e) { - e.stopPropagation(); - return this.focus(e.target); - }; - - Menu.prototype.focus = function(entry) { - var bottom, cHeight, cWidth, eRect, focused, i, left, len, ref, ref1, ref2, right, sRect, style, submenu, top; - while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { - $.rmClass(focused, 'focused'); - } - ref = $$('.focused', entry); - for (i = 0, len = ref.length; i < len; i++) { - focused = ref[i]; - $.rmClass(focused, 'focused'); - } - $.addClass(entry, 'focused'); - if (!(submenu = $('.submenu', entry))) { - return; - } - sRect = submenu.getBoundingClientRect(); - eRect = entry.getBoundingClientRect(); - cHeight = doc.clientHeight; - cWidth = doc.clientWidth; - ref1 = eRect.top + sRect.height < cHeight ? ['0px', 'auto'] : ['auto', '0px'], top = ref1[0], bottom = ref1[1]; - ref2 = eRect.right + sRect.width < cWidth - 150 ? ['100%', 'auto'] : ['auto', '100%'], left = ref2[0], right = ref2[1]; - style = submenu.style; - style.top = top; - style.bottom = bottom; - style.left = left; - return style.right = right; - }; - - Menu.prototype.addEntry = function(entry) { - this.parseEntry(entry); - return this.entries.push(entry); - }; - - Menu.prototype.parseEntry = function(entry) { - var el, i, len, subEntries, subEntry; - el = entry.el, subEntries = entry.subEntries; - $.addClass(el, 'entry'); - $.on(el, 'focus mouseover', this.onFocus); - el.style.order = entry.order || 100; - if (!subEntries) { - return; - } - $.addClass(el, 'has-submenu'); - for (i = 0, len = subEntries.length; i < len; i++) { - subEntry = subEntries[i]; - this.parseEntry(subEntry); - } - }; - - return Menu; - - })(); - - dragstart = function(e) { - var el, isTouching, o, rect, ref, screenHeight, screenWidth; - if (e.type === 'mousedown' && e.button !== 0) { - return; - } - e.preventDefault(); - if (isTouching = e.type === 'touchstart') { - e = e.changedTouches[e.changedTouches.length - 1]; - } - el = $.x('ancestor::div[contains(@class,"dialog")][1]', this); - rect = el.getBoundingClientRect(); - screenHeight = doc.clientHeight; - screenWidth = doc.clientWidth; - o = { - id: el.id, - style: el.style, - dx: e.clientX - rect.left, - dy: e.clientY - rect.top, - height: screenHeight - rect.height, - width: screenWidth - rect.width, - screenHeight: screenHeight, - screenWidth: screenWidth, - isTouching: isTouching - }; - ref = Conf['Header auto-hide'] || !Conf['Fixed Header'] ? [0, 0] : Conf['Bottom Header'] ? [0, Header.bar.getBoundingClientRect().height] : [Header.bar.getBoundingClientRect().height, 0], o.topBorder = ref[0], o.bottomBorder = ref[1]; - if (isTouching) { - o.identifier = e.identifier; - o.move = touchmove.bind(o); - o.up = touchend.bind(o); - $.on(d, 'touchmove', o.move); - return $.on(d, 'touchend touchcancel', o.up); - } else { - o.move = drag.bind(o); - o.up = dragend.bind(o); - $.on(d, 'mousemove', o.move); - return $.on(d, 'mouseup', o.up); - } - }; - - touchmove = function(e) { - var i, len, ref, touch; - ref = e.changedTouches; - for (i = 0, len = ref.length; i < len; i++) { - touch = ref[i]; - if (touch.identifier === this.identifier) { - drag.call(this, touch); - return; - } - } - }; - - drag = function(e) { - var bottom, clientX, clientY, left, right, style, top; - clientX = e.clientX, clientY = e.clientY; - left = clientX - this.dx; - left = left < 10 ? 0 : this.width - left < 10 ? '' : left / this.screenWidth * 100 + '%'; - top = clientY - this.dy; - top = top < (10 + this.topBorder) ? this.topBorder + 'px' : this.height - top < (10 + this.bottomBorder) ? '' : top / this.screenHeight * 100 + '%'; - right = left === '' ? 0 : ''; - bottom = top === '' ? this.bottomBorder + 'px' : ''; - style = this.style; - style.left = left; - style.right = right; - style.top = top; - return style.bottom = bottom; - }; - - touchend = function(e) { - var i, len, ref, touch; - ref = e.changedTouches; - for (i = 0, len = ref.length; i < len; i++) { - touch = ref[i]; - if (touch.identifier === this.identifier) { - dragend.call(this); - return; - } - } - }; - - dragend = function() { - if (this.isTouching) { - $.off(d, 'touchmove', this.move); - $.off(d, 'touchend touchcancel', this.up); - } else { - $.off(d, 'mousemove', this.move); - $.off(d, 'mouseup', this.up); - } - return $.set(this.id + ".position", this.style.cssText); - }; - - hoverstart = function(arg) { - var cb, el, endEvents, height, latestEvent, noRemove, o, rect, ref, root, width; - root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, height = arg.height, width = arg.width, cb = arg.cb, noRemove = arg.noRemove; - rect = root.getBoundingClientRect(); - o = { - root: root, - el: el, - style: el.style, - isImage: (ref = el.nodeName) === 'IMG' || ref === 'VIDEO', - cb: cb, - endEvents: endEvents, - latestEvent: latestEvent, - clientHeight: doc.clientHeight, - clientWidth: doc.clientWidth, - height: height, - width: width, - noRemove: noRemove, - clientX: (rect.left + rect.right) / 2, - clientY: (rect.top + rect.bottom) / 2 - }; - o.hover = hover.bind(o); - o.hoverend = hoverend.bind(o); - o.hover(o.latestEvent); - new MutationObserver(function() { - if (el.parentNode) { - return o.hover(o.latestEvent); - } - }).observe(el, { - childList: true - }); - $.on(root, endEvents, o.hoverend); - if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) { - $.on(d, 'keydown', o.hoverend); - } - $.on(root, 'mousemove', o.hover); - o.workaround = function(e) { - if (!root.contains(e.target)) { - return o.hoverend(e); - } - }; - return $.on(doc, 'mousemove', o.workaround); - }; - - hoverstart.padding = 25; - - hover = function(e) { - var clientX, clientY, height, left, marginX, ref, ref1, right, style, threshold, top, width; - this.latestEvent = e; - height = (this.height || this.el.offsetHeight) + hoverstart.padding; - width = this.width || this.el.offsetWidth; - ref = Conf['Follow Cursor'] ? e : this, clientX = ref.clientX, clientY = ref.clientY; - top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120)); - threshold = this.clientWidth / 2; - if (!this.isImage) { - threshold = Math.max(threshold, this.clientWidth - 400); - } - marginX = (clientX <= threshold ? clientX : this.clientWidth - clientX) + 45; - if (this.isImage) { - marginX = Math.min(marginX, this.clientWidth - width); - } - marginX += 'px'; - ref1 = clientX <= threshold ? [marginX, ''] : ['', marginX], left = ref1[0], right = ref1[1]; - style = this.style; - style.top = top + 'px'; - style.left = left; - return style.right = right; - }; - - hoverend = function(e) { - if (e.type === 'keydown' && e.keyCode !== 13 || e.target.nodeName === "TEXTAREA") { - return; - } - if (!this.noRemove) { - $.rm(this.el); - } - $.off(this.root, this.endEvents, this.hoverend); - $.off(d, 'keydown', this.hoverend); - $.off(this.root, 'mousemove', this.hover); - $.off(doc, 'mousemove', this.workaround); - if (this.cb) { - return this.cb.call(this); - } - }; - - checkbox = function(name, text, checked) { - var input, label; - if (checked == null) { - checked = Conf[name]; - } - label = $.el('label'); - input = $.el('input', { - type: 'checkbox', - name: name, - checked: checked - }); - $.add(label, [input, $.tn(" " + text)]); - return label; - }; - - UI = { - dialog: dialog, - Menu: Menu, - hover: hoverstart, - checkbox: checkbox - }; - - return UI; - -}).call(this); - -FappeTyme = (function() { - var FappeTyme; - - FappeTyme = { - init: function() { - var el, i, indicator, lc, len, ref, ref1, type; - if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive'))) { - return; - } - this.nodes = {}; - this.enabled = { - fappe: false, - werk: Conf['werk'] - }; - ref1 = ["Fappe", "Werk"]; - for (i = 0, len = ref1.length; i < len; i++) { - type = ref1[i]; - if (!Conf[type + " Tyme"]) { - continue; - } - lc = type.toLowerCase(); - el = UI.checkbox(lc, type + " Tyme", false); - el.title = type + " Tyme"; - this.nodes[lc] = el.firstElementChild; - if (Conf[lc]) { - this.set(lc, true); - } - $.on(this.nodes[lc], 'change', this.toggle.bind(this, lc)); - Header.menu.addEntry({ - el: el, - order: 97 - }); - indicator = $.el('span', { - className: 'indicator', - textContent: type[0], - title: type + " Tyme active" - }); - $.on(indicator, 'click', function() { - var check; - check = $.getOwn(FappeTyme.nodes, this.parentNode.id.replace('shortcut-', '')); - check.checked = !check.checked; - return $.event('change', null, check); - }); - Header.addShortcut(lc, indicator, 410); - } - if (Conf['Werk Tyme']) { - $.sync('werk', this.set.bind(this, 'werk')); - } - Callbacks.Post.push({ - name: 'Fappe Tyme', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Werk Tyme', - cb: this.catalogNode - }); - }, - node: function() { - return this.nodes.root.classList.toggle('noFile', !this.files.length); - }, - catalogNode: function() { - var file, filename; - file = this.thread.OP.files[0]; - if (!file) { - return; - } - filename = $.el('div', { - textContent: file.name, - className: 'werkTyme-filename' - }); - return $.add(this.nodes.thumb.parentNode, filename); - }, - set: function(type, enabled) { - this.enabled[type] = this.nodes[type].checked = enabled; - return $[(enabled ? 'add' : 'rm') + "Class"](doc, type + "Tyme"); - }, - toggle: function(type) { - this.set(type, !this.enabled[type]); - if (type === 'werk') { - return $.cb.checked.call(this.nodes[type]); - } - } - }; - - return FappeTyme; - -}).call(this); - -Gallery = (function() { - var Gallery; - - Gallery = { - init: function() { - var el, ref; - if (!(this.enabled = Conf['Gallery'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.delay = Conf['Slide Delay']; - el = $.el('a', { - href: 'javascript:;', - title: 'Gallery', - className: 'fa fa-picture-o', - textContent: 'Gallery' - }); - $.on(el, 'click', this.cb.toggle); - Header.addShortcut('gallery', el, 530); - return Callbacks.Post.push({ - name: 'Gallery', - cb: this.node - }); - }, - node: function() { - var file, i, len, ref, results; - ref = this.files; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (!file.thumb) { - continue; - } - if (Gallery.nodes) { - Gallery.generateThumb(this, file); - Gallery.nodes.total.textContent = Gallery.images.length; - } - if (!(Conf['Image Expansion'] || (g.SITE.software === 'tinyboard' && Main.jsEnabled))) { - results.push($.on(file.thumbLink, 'click', Gallery.cb.image)); - } else { - results.push(void 0); - } - } - return results; - }, - build: function(image) { - var candidate, cb, dialog, entry, file, i, j, k, key, len, len1, len2, menuButton, nodes, post, postThumb, ref, ref1, ref2, ref3, thumb, value; - cb = Gallery.cb; - if (Conf['Fullscreen Gallery']) { - $.one(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', function() { - return $.on(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', cb.close); - }); - if (typeof doc.mozRequestFullScreen === "function") { - doc.mozRequestFullScreen(); - } - if (typeof doc.webkitRequestFullScreen === "function") { - doc.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); - } - } - Gallery.images = []; - nodes = Gallery.nodes = {}; - Gallery.fileIDs = $.dict(); - Gallery.slideshow = false; - nodes.el = dialog = $.el('div', { - id: 'a-gallery' - }); - $.extend(dialog, {innerHTML: "
    ×
    /
    "}); - ref = { - buttons: '.gal-buttons', - frame: '.gal-image', - name: '.gal-name', - count: '.count', - total: '.total', - sauce: '.gal-sauce', - thumbs: '.gal-thumbnails', - next: '.gal-image a', - current: '.gal-image img' - }; - for (key in ref) { - value = ref[key]; - nodes[key] = $(value, dialog); - } - menuButton = $('.menu-button', dialog); - nodes.menu = new UI.Menu('gallery'); - $.on(nodes.frame, 'click', cb.blank); - if (Conf['Mouse Wheel Volume']) { - $.on(nodes.frame, 'wheel', Volume.wheel); - } - $.on(nodes.next, 'click', cb.click); - $.on(nodes.name, 'click', ImageCommon.download); - $.on($('.gal-prev', dialog), 'click', cb.prev); - $.on($('.gal-next', dialog), 'click', cb.next); - $.on($('.gal-start', dialog), 'click', cb.start); - $.on($('.gal-stop', dialog), 'click', cb.stop); - $.on($('.gal-close', dialog), 'click', cb.close); - $.on(menuButton, 'click', function(e) { - return nodes.menu.toggle(e, this, g); - }); - ref1 = Gallery.menu.createSubEntries(); - for (i = 0, len = ref1.length; i < len; i++) { - entry = ref1[i]; - entry.order = 0; - nodes.menu.addEntry(entry); - } - $.on(d, 'keydown', cb.keybinds); - if (Conf['Keybinds']) { - $.off(d, 'keydown', Keybinds.keydown); - } - $.on(window, 'resize', Gallery.cb.setHeight); - ref2 = $$(g.SITE.selectors.file.thumb); - for (j = 0, len1 = ref2.length; j < len1; j++) { - postThumb = ref2[j]; - if (!(post = Get.postFromNode(postThumb))) { - continue; - } - ref3 = post.files; - for (k = 0, len2 = ref3.length; k < len2; k++) { - file = ref3[k]; - if (!file.thumb) { - continue; - } - Gallery.generateThumb(post, file); - if (!image && Gallery.fileIDs[post.fullID + "." + file.index]) { - candidate = file.thumbLink; - if (Header.getTopOf(candidate) + candidate.getBoundingClientRect().height >= 0) { - image = candidate; - } - } - } - } - $.addClass(doc, 'gallery-open'); - $.add(d.body, dialog); - nodes.thumbs.scrollTop = 0; - nodes.current.parentElement.scrollTop = 0; - if (image) { - thumb = $("[href='" + image.href + "']", nodes.thumbs); - } - thumb || (thumb = Gallery.images[Gallery.images.length - 1]); - if (thumb) { - Gallery.open(thumb); - } - doc.style.overflow = 'hidden'; - return nodes.total.textContent = Gallery.images.length; - }, - generateThumb: function(post, file) { - var thumb, thumbImg; - if (post.isClone || post.isHidden) { - return; - } - if (!(file && file.thumb && (file.isImage || file.isVideo || Conf['PDF in Gallery']))) { - return; - } - if (Gallery.fileIDs[post.fullID + "." + file.index]) { - return; - } - Gallery.fileIDs[post.fullID + "." + file.index] = true; - thumb = $.el('a', { - className: 'gal-thumb', - href: file.url, - target: '_blank', - title: file.name - }); - thumb.dataset.id = Gallery.images.length; - thumb.dataset.post = post.fullID; - thumb.dataset.file = file.index; - thumbImg = file.thumb.cloneNode(false); - thumbImg.style.cssText = ''; - $.add(thumb, thumbImg); - $.on(thumb, 'click', Gallery.cb.open); - Gallery.images.push(thumb); - return $.add(Gallery.nodes.thumbs, thumb); - }, - load: function(thumb, errorCB) { - var elType, ext, file; - ext = thumb.href.match(/\w*$/); - elType = $.getOwn({ - 'webm': 'video', - 'mp4': 'video', - 'ogv': 'video', - 'pdf': 'iframe' - }, ext) || 'img'; - file = $.el(elType); - $.extend(file.dataset, thumb.dataset); - $.on(file, 'error', errorCB); - file.src = thumb.href; - return file; - }, - open: function(thumb) { - var el, file, i, len, link, newID, node, nodes, oldID, post, ref, ref1, sauces; - nodes = Gallery.nodes; - oldID = +nodes.current.dataset.id; - newID = +thumb.dataset.id; - if (el = Gallery.images[oldID]) { - $.rmClass(el, 'gal-highlight'); - } - $.addClass(thumb, 'gal-highlight'); - nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; - if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { - file = Gallery.cache; - $.off(file, 'error', Gallery.cacheError); - $.on(file, 'error', Gallery.error); - } else { - file = Gallery.load(thumb, Gallery.error); - } - $.off(nodes.current, 'error', Gallery.error); - ImageCommon.pause(nodes.current); - $.replace(nodes.current, file); - nodes.current = file; - if (file.nodeName === 'VIDEO') { - file.loop = true; - Volume.setup(file); - if (Conf['Autoplay']) { - file.play(); - } - if (Conf['Show Controls']) { - ImageCommon.addControls(file); - } - } - doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); - Gallery.cb.setHeight(); - nodes.count.textContent = +thumb.dataset.id + 1; - nodes.name.download = nodes.name.textContent = thumb.title; - nodes.name.href = thumb.href; - nodes.frame.scrollTop = 0; - nodes.next.focus(); - $.rmAll(nodes.sauce); - if (Conf['Sauce'] && Sauce.links && (post = g.posts.get(file.dataset.post))) { - sauces = []; - ref1 = Sauce.links; - for (i = 0, len = ref1.length; i < len; i++) { - link = ref1[i]; - if ((node = Sauce.createSauceLink(link, post, post.files[+file.dataset.file]))) { - sauces.push($.tn(' '), node); - } - } - $.add(nodes.sauce, sauces); - } - if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { - Gallery.setupTimer(); - } else { - Gallery.cb.stop(); - } - if (Conf['Scroll to Post'] && (post = g.posts.get(file.dataset.post))) { - Header.scrollTo(post.nodes.root); - } - if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { - return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); - } - }, - error: function() { - var file, post, ref; - if (((ref = this.error) != null ? ref.code : void 0) === MediaError.MEDIA_ERR_DECODE) { - return new Notice('error', 'Corrupt or unplayable video', 30); - } - if (ImageCommon.isFromArchive(this)) { - return; - } - post = g.posts.get(this.dataset.post); - file = post.files[+this.dataset.file]; - return ImageCommon.error(this, post, file, null, (function(_this) { - return function(url) { - if (!url) { - return; - } - Gallery.images[+_this.dataset.id].href = url; - if (Gallery.nodes.current === _this) { - return _this.src = url; - } - }; - })(this)); - }, - cacheError: function() { - return delete Gallery.cache; - }, - cleanupTimer: function() { - var current; - clearTimeout(Gallery.timeoutID); - current = Gallery.nodes.current; - $.off(current, 'canplaythrough load', Gallery.startTimer); - return $.off(current, 'ended', Gallery.cb.next); - }, - startTimer: function() { - return Gallery.timeoutID = setTimeout(Gallery.checkTimer, Gallery.delay * $.SECOND); - }, - setupTimer: function() { - var current, isVideo; - Gallery.cleanupTimer(); - current = Gallery.nodes.current; - isVideo = current.nodeName === 'VIDEO'; - if (isVideo) { - current.play(); - } - if ((isVideo ? current.readyState >= 4 : current.complete) || current.nodeName === 'IFRAME') { - return Gallery.startTimer(); - } else { - return $.on(current, (isVideo ? 'canplaythrough' : 'load'), Gallery.startTimer); - } - }, - checkTimer: function() { - var current; - current = Gallery.nodes.current; - if (current.nodeName === 'VIDEO' && !current.paused) { - $.on(current, 'ended', Gallery.cb.next); - return current.loop = false; - } else { - return Gallery.cb.next(); - } - }, - cb: { - keybinds: function(e) { - var cb, key; - if (!(key = Keybinds.keyCode(e))) { - return; - } - cb = (function() { - switch (key) { - case Conf['Close']: - case Conf['Open Gallery']: - return Gallery.cb.close; - case Conf['Next Gallery Image']: - return Gallery.cb.next; - case Conf['Advance Gallery']: - return Gallery.cb.advance; - case Conf['Previous Gallery Image']: - return Gallery.cb.prev; - case Conf['Pause']: - return Gallery.cb.pause; - case Conf['Slideshow']: - return Gallery.cb.toggleSlideshow; - case Conf['Rotate image anticlockwise']: - return Gallery.cb.rotateLeft; - case Conf['Rotate image clockwise']: - return Gallery.cb.rotateRight; - case Conf['Download Gallery Image']: - return Gallery.cb.download; - } - })(); - if (!cb) { - return; - } - e.stopPropagation(); - e.preventDefault(); - return cb(); - }, - open: function(e) { - if (e) { - e.preventDefault(); - } - if (this) { - return Gallery.open(this); - } - }, - image: function(e) { - e.preventDefault(); - e.stopPropagation(); - return Gallery.build(this); - }, - prev: function() { - return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id - 1] || Gallery.images[Gallery.images.length - 1]); - }, - next: function() { - return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id + 1] || Gallery.images[0]); - }, - click: function(e) { - if (ImageCommon.onControls(e)) { - return; - } - e.preventDefault(); - return Gallery.cb.advance(); - }, - advance: function() { - if (!Conf['Autoplay'] && Gallery.nodes.current.paused) { - return Gallery.nodes.current.play(); - } else { - return Gallery.cb.next(); - } - }, - toggle: function() { - return (Gallery.nodes ? Gallery.cb.close : Gallery.build)(); - }, - blank: function(e) { - if (e.target === this) { - return Gallery.cb.close(); - } - }, - toggleSlideshow: function() { - return Gallery.cb[Gallery.slideshow ? 'stop' : 'start'](); - }, - download: function() { - var name; - name = $('.gal-name'); - return name.click(); - }, - pause: function() { - var current; - Gallery.cb.stop(); - current = Gallery.nodes.current; - if (current.nodeName === 'VIDEO') { - return current[current.paused ? 'play' : 'pause'](); - } - }, - start: function() { - $.addClass(Gallery.nodes.buttons, 'gal-playing'); - Gallery.slideshow = true; - return Gallery.setupTimer(); - }, - stop: function() { - var current; - if (!Gallery.slideshow) { - return; - } - Gallery.cleanupTimer(); - current = Gallery.nodes.current; - if (current.nodeName === 'VIDEO') { - current.loop = true; - } - $.rmClass(Gallery.nodes.buttons, 'gal-playing'); - return Gallery.slideshow = false; - }, - rotateLeft: function() { - return Gallery.cb.rotate(270); - }, - rotateRight: function() { - return Gallery.cb.rotate(90); - }, - rotate: $.debounce(100, function(delta) { - var current; - current = Gallery.nodes.current; - if (current.nodeName === 'IFRAME') { - return; - } - current.dataRotate = ((current.dataRotate || 0) + delta) % 360; - current.style.transform = "rotate(" + current.dataRotate + "deg)"; - return Gallery.cb.setHeight(); - }), - close: function() { - $.off(Gallery.nodes.current, 'error', Gallery.error); - ImageCommon.pause(Gallery.nodes.current); - $.rm(Gallery.nodes.el); - $.rmClass(doc, 'gallery-open'); - if (Conf['Fullscreen Gallery']) { - $.off(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', Gallery.cb.close); - if (typeof d.mozCancelFullScreen === "function") { - d.mozCancelFullScreen(); - } - if (typeof d.webkitExitFullscreen === "function") { - d.webkitExitFullscreen(); - } - } - delete Gallery.nodes; - delete Gallery.fileIDs; - doc.style.overflow = ''; - $.off(d, 'keydown', Gallery.cb.keybinds); - if (Conf['Keybinds']) { - $.on(d, 'keydown', Keybinds.keydown); - } - $.off(window, 'resize', Gallery.cb.setHeight); - return clearTimeout(Gallery.timeoutID); - }, - setFitness: function() { - return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); - }, - setHeight: $.debounce(100, function() { - var containerHeight, containerWidth, current, dim, frame, height, margin, minHeight, ref, ref1, ref2, ref3, style, width; - ref = Gallery.nodes, current = ref.current, frame = ref.frame; - style = current.style; - if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts.get(current.dataset.post)) != null ? ref1.files[+current.dataset.file].dimensions : void 0)) { - ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; - containerWidth = frame.clientWidth; - containerHeight = doc.clientHeight - 25; - if ((current.dataRotate || 0) % 180 === 90) { - ref3 = [containerHeight, containerWidth], containerWidth = ref3[0], containerHeight = ref3[1]; - } - minHeight = Math.min(containerHeight, height / width * containerWidth); - style.minHeight = minHeight + 'px'; - style.minWidth = (width / height * minHeight) + 'px'; - } else { - style.minHeight = style.minWidth = ''; - } - if ((current.dataRotate || 0) % 180 === 90) { - style.maxWidth = Conf['Fit Height'] ? (doc.clientHeight - 25) + "px" : 'none'; - style.maxHeight = Conf['Fit Width'] ? frame.clientWidth + "px" : 'none'; - margin = (current.clientWidth - current.clientHeight) / 2; - return style.margin = margin + "px " + (-margin) + "px"; - } else { - return style.maxWidth = style.maxHeight = style.margin = ''; - } - }), - setDelay: function() { - return Gallery.delay = +this.value; - } - }, - menu: { - init: function() { - var el; - if (!Gallery.enabled) { - return; - } - el = $.el('span', { - textContent: 'Gallery', - className: 'gallery-link' - }); - return Header.menu.addEntry({ - el: el, - order: 105, - subEntries: Gallery.menu.createSubEntries() - }); - }, - createSubEntry: function(name) { - var input, label; - label = UI.checkbox(name, name); - input = label.firstElementChild; - if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { - $.on(input, 'change', Gallery.cb.setFitness); - } - $.event('change', null, input); - $.on(input, 'change', $.cb.checked); - if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { - $.on(input, 'change', Gallery.cb.setHeight); - } - return { - el: label - }; - }, - createSubEntries: function() { - var delayInput, delayLabel, item, subEntries; - subEntries = (function() { - var i, len, ref, results; - ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', 'Scroll to Post']; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - item = ref[i]; - results.push(Gallery.menu.createSubEntry(item)); - } - return results; - })(); - delayLabel = $.el('label', {innerHTML: "Slide Delay: "}); - delayInput = delayLabel.firstElementChild; - delayInput.value = Gallery.delay; - $.on(delayInput, 'change', Gallery.cb.setDelay); - $.on(delayInput, 'change', $.cb.value); - subEntries.push({ - el: delayLabel - }); - return subEntries; - } - } - }; - - return Gallery; - -}).call(this); - -ImageCommon = (function() { - var ImageCommon, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - ImageCommon = { - pause: function(video) { - if (video.nodeName !== 'VIDEO') { - return; - } - video.pause(); - $.off(video, 'volumechange', Volume.change); - return video.muted = true; - }, - rewind: function(el) { - if (el.nodeName === 'VIDEO') { - if (el.readyState >= el.HAVE_METADATA) { - return el.currentTime = 0; - } - } else if (/\.gif$/.test(el.src)) { - return $.queueTask(function() { - return el.src = el.src; - }); - } - }, - pushCache: function(el) { - ImageCommon.cache = el; - return $.on(el, 'error', ImageCommon.cacheError); - }, - popCache: function() { - var el; - el = ImageCommon.cache; - $.off(el, 'error', ImageCommon.cacheError); - delete ImageCommon.cache; - return el; - }, - cacheError: function() { - if (ImageCommon.cache === this) { - return delete ImageCommon.cache; - } - }, - decodeError: function(file, fileObj) { - var message, ref; - if (((ref = file.error) != null ? ref.code : void 0) !== MediaError.MEDIA_ERR_DECODE) { - return false; - } - if (!(message = $('.warning', fileObj.thumb.parentNode))) { - message = $.el('div', { - className: 'warning' - }); - $.after(fileObj.thumb, message); - } - message.textContent = 'Error: Corrupt or unplayable video'; - return true; - }, - isFromArchive: function(file) { - return g.SITE.software === 'yotsuba' && !ImageHost.test(file.src.split('/')[2]); - }, - error: function(file, post, fileObj, delay, cb) { - var base, parseJSON, redirect, src, threadJSON, timeoutID, url; - src = fileObj.url.split('/'); - url = null; - if (g.SITE.software === 'yotsuba' && Conf['404 Redirect']) { - url = Redirect.to('file', { - boardID: post.board.ID, - filename: src[src.length - 1] - }); - } - if (!(url && Redirect.securityCheck(url))) { - url = null; - } - if ((post.isDead || fileObj.isDead) && !ImageCommon.isFromArchive(file)) { - return cb(url); - } - if (delay != null) { - timeoutID = setTimeout((function() { - return cb(url); - }), delay); - } - if (post.isDead || fileObj.isDead) { - return; - } - redirect = function() { - if (!ImageCommon.isFromArchive(file)) { - if (delay != null) { - clearTimeout(timeoutID); - } - return cb(url); - } - }; - threadJSON = typeof (base = g.SITE.urls).threadJSON === "function" ? base.threadJSON(post) : void 0; - if (!threadJSON) { - return; - } - parseJSON = function(isArchiveURL) { - var archivedThreadJSON, base1, i, len, postObj, ref, ref1; - if (this.status === 404) { - if (!isArchiveURL && (archivedThreadJSON = typeof (base1 = g.SITE.urls).archivedThreadJSON === "function" ? base1.archivedThreadJSON(post) : void 0)) { - $.ajax(archivedThreadJSON, { - onloadend: function() { - return parseJSON.call(this, true); - } - }); - } else { - post.kill(!post.isClone, fileObj.index); - } - } - if (this.status !== 200) { - return redirect(); - } - ref = this.response.posts; - for (i = 0, len = ref.length; i < len; i++) { - postObj = ref[i]; - if (postObj.no === post.ID) { - break; - } - } - if (postObj.no !== post.ID) { - post.kill(); - return redirect(); - } else if (ref1 = fileObj.docIndex, indexOf.call(g.SITE.Build.parseJSON(postObj, post.board).filesDeleted, ref1) >= 0) { - post.kill(true); - return redirect(); - } else { - return url = fileObj.url; - } - }; - return $.ajax(threadJSON, { - onloadend: function() { - return parseJSON.call(this); - } - }); - }, - addControls: function(video) { - var handler; - handler = function() { - var t; - $.off(video, 'mouseover', handler); - t = new Date().getTime(); - return $.asap((function() { - return $.engine !== 'gecko' || (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || new Date().getTime() >= t + 1000; - }), function() { - return video.controls = true; - }); - }; - return $.on(video, 'mouseover', handler); - }, - onControls: function(e) { - return (Conf['Show Controls'] && Conf['Click Passthrough'] && e.target.nodeName === 'VIDEO') || (e.target.controls && e.target.getBoundingClientRect().bottom - e.clientY < 35); - }, - download: function(e) { - var download, href, ref; - if (this.protocol === 'blob:') { - return true; - } - e.preventDefault(); - ref = this, href = ref.href, download = ref.download; - return CrossOrigin.file(href, function(blob) { - var a; - if (blob) { - a = $.el('a', { - href: URL.createObjectURL(blob), - download: download, - hidden: true - }); - $.add(d.body, a); - a.click(); - return $.rm(a); - } else { - return new Notice('warning', "Could not download " + href, 20); - } - }); - } - }; - - return ImageCommon; - -}).call(this); - -ImageExpand = (function() { - var ImageExpand, - slice = [].slice; - - ImageExpand = { - init: function() { - var ref; - if (!(this.enabled = Conf['Image Expansion'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.EAI = $.el('a', { - className: 'expand-all-shortcut fa fa-expand', - textContent: 'EAI', - title: 'Expand All Images', - href: 'javascript:;' - }); - $.on(this.EAI, 'click', this.cb.toggleAll); - Header.addShortcut('expand-all', this.EAI, 520); - $.on(d, 'scroll visibilitychange', this.cb.playVideos); - this.videoControls = $.el('span', { - className: 'video-controls' - }); - $.extend(this.videoControls, {innerHTML: " contract"}); - return Callbacks.Post.push({ - name: 'Image Expansion', - cb: this.node - }); - }, - node: function() { - var ref; - if (!(this.file && (this.file.isImage || this.file.isVideo))) { - return; - } - $.on(this.file.thumbLink, 'click', ImageExpand.cb.toggle); - if (this.isClone) { - if (this.file.isExpanding) { - ImageExpand.contract(this); - return ImageExpand.expand(this); - } else if (this.file.isExpanded && this.file.isVideo) { - Volume.setup(this.file.fullImage); - ImageExpand.setupVideoCB(this); - return ImageExpand.setupVideo(this, !((ref = this.origin.file.fullImage) != null ? ref.paused : void 0) || this.origin.file.wasPlaying, this.file.fullImage.controls); - } - } else if (ImageExpand.on && !this.isHidden && !this.isFetchedQuote && (Conf['Expand spoilers'] || !this.file.isSpoiler) && (Conf['Expand videos'] || !this.file.isVideo)) { - return ImageExpand.expand(this); - } - }, - cb: { - toggle: function(e) { - var file, post, ref; - if ($.modifiedClick(e)) { - return; - } - post = Get.postFromNode(this); - file = post.file; - if (file.isExpanded && ImageCommon.onControls(e)) { - return; - } - e.preventDefault(); - if (!Conf['Autoplay'] && ((ref = file.fullImage) != null ? ref.paused : void 0)) { - return file.fullImage.play(); - } else { - return ImageExpand.toggle(post); - } - }, - toggleAll: function() { - var func, threadRoot, toggle; - $.event('CloseMenu'); - threadRoot = Nav.getThread(); - toggle = function(post) { - var file; - file = post.file; - if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { - return; - } - if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || !Conf['Expand videos'] && file.isVideo || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0 || Conf['Expand thread only'] && g.VIEW === 'index' && !(threadRoot != null ? threadRoot.contains(file.thumb) : void 0))) { - return; - } - return $.queueTask(func, post); - }; - if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) { - ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress'; - ImageExpand.EAI.title = 'Contract All Images'; - func = ImageExpand.expand; - } else { - ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand'; - ImageExpand.EAI.title = 'Expand All Images'; - func = ImageExpand.contract; - } - return g.posts.forEach(function(post) { - var i, len, ref; - ref = [post].concat(slice.call(post.clones)); - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - toggle(post); - } - }); - }, - playVideos: function() { - return g.posts.forEach(function(post) { - var file, i, len, ref, video, visible; - ref = [post].concat(slice.call(post.clones)); - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - file = post.file; - if (!(file && file.isVideo && file.isExpanded)) { - continue; - } - video = file.fullImage; - visible = ($.hasAudio(video) && !video.muted) || Header.isNodeVisible(video); - if (visible && file.wasPlaying) { - delete file.wasPlaying; - video.play(); - } else if (!visible && !video.paused) { - file.wasPlaying = true; - video.pause(); - } - } - }); - }, - setFitness: function() { - return $[this.checked ? 'addClass' : 'rmClass'](doc, this.name.toLowerCase().replace(/\s+/g, '-')); - } - }, - toggle: function(post) { - var next; - if (!(post.file.isExpanding || post.file.isExpanded)) { - post.file.scrollIntoView = Conf['Scroll into view']; - ImageExpand.expand(post); - return; - } - ImageExpand.contract(post); - if (Conf['Advance on contract']) { - next = post.nodes.root; - while (next = $.x("following::div[contains(@class,'postContainer')][1]", next)) { - if (!($('.stub', next) || next.offsetHeight === 0)) { - break; - } - } - if (next) { - return Header.scrollTo(next); - } - } - }, - contract: function(post) { - var bottom, cb, el, eventName, file, i, len, oldHeight, ref, ref1, scrollY, top, x; - file = post.file; - if (el = file.fullImage) { - top = Header.getTopOf(el); - bottom = top + el.getBoundingClientRect().height; - oldHeight = d.body.clientHeight; - scrollY = window.scrollY; - } - $.rmClass(post.nodes.root, 'expanded-image'); - $.rmClass(file.thumb, 'expanding'); - $.rm(file.videoControls); - file.thumbLink.href = file.url; - file.thumbLink.target = '_blank'; - ref = ['isExpanding', 'isExpanded', 'videoControls', 'wasPlaying', 'scrollIntoView']; - for (i = 0, len = ref.length; i < len; i++) { - x = ref[i]; - delete file[x]; - } - if (!el) { - return; - } - if (doc.contains(el)) { - if (bottom <= 0) { - window.scrollBy(0, scrollY - window.scrollY + d.body.clientHeight - oldHeight); - } else { - Header.scrollToIfNeeded(post.nodes.root); - } - if (window.scrollX > 0) { - window.scrollBy(-window.scrollX, 0); - } - } - $.off(el, 'error', ImageExpand.error); - ImageCommon.pushCache(el); - if (file.isVideo) { - ImageCommon.pause(el); - ref1 = ImageExpand.videoCB; - for (eventName in ref1) { - cb = ref1[eventName]; - $.off(el, eventName, cb); - } - } - if (Conf['Restart when Opened']) { - ImageCommon.rewind(file.thumb); - } - delete file.fullImage; - return $.queueTask(function() { - if (file.isExpanding || file.isExpanded) { - return; - } - $.rmClass(el, 'full-image'); - if (el.id) { - return; - } - return $.rm(el); - }); - }, - expand: function(post, src) { - var el, file, isVideo, ref, thumb, thumbLink; - file = post.file; - thumb = file.thumb, thumbLink = file.thumbLink, isVideo = file.isVideo; - if (post.isHidden || file.isExpanding || file.isExpanded) { - return; - } - $.addClass(thumb, 'expanding'); - file.isExpanding = true; - if (file.fullImage) { - el = file.fullImage; - } else if (((ref = ImageCommon.cache) != null ? ref.dataset.fileID : void 0) === (post.fullID + "." + file.index)) { - el = file.fullImage = ImageCommon.popCache(); - $.on(el, 'error', ImageExpand.error); - if (Conf['Restart when Opened'] && el.id !== 'ihover') { - ImageCommon.rewind(el); - } - el.removeAttribute('id'); - } else { - el = file.fullImage = $.el((isVideo ? 'video' : 'img')); - el.dataset.fileID = post.fullID + "." + file.index; - $.on(el, 'error', ImageExpand.error); - el.src = src || file.url; - } - el.className = 'full-image'; - $.after(thumb, el); - if (isVideo) { - if (!file.videoControls) { - file.videoControls = ImageExpand.videoControls.cloneNode(true); - $.add(file.text, file.videoControls); - } - thumbLink.removeAttribute('href'); - thumbLink.removeAttribute('target'); - el.loop = true; - Volume.setup(el); - ImageExpand.setupVideoCB(post); - } - if (!isVideo) { - return $.asap((function() { - return el.naturalHeight; - }), function() { - return ImageExpand.completeExpand(post); - }); - } else if (el.readyState >= el.HAVE_METADATA) { - return ImageExpand.completeExpand(post); - } else { - return $.on(el, 'loadedmetadata', function() { - return ImageExpand.completeExpand(post); - }); - } - }, - completeExpand: function(post) { - var bottom, file, imageBottom, oldHeight, scrollY; - file = post.file; - if (!file.isExpanding) { - return; - } - bottom = Header.getTopOf(file.thumb) + file.thumb.getBoundingClientRect().height; - oldHeight = d.body.clientHeight; - scrollY = window.scrollY; - $.addClass(post.nodes.root, 'expanded-image'); - $.rmClass(file.thumb, 'expanding'); - file.isExpanded = true; - delete file.isExpanding; - if (doc.contains(post.nodes.root) && bottom <= 0) { - window.scrollBy(0, scrollY - window.scrollY + d.body.clientHeight - oldHeight); - } - if (file.scrollIntoView) { - delete file.scrollIntoView; - imageBottom = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); - if (imageBottom < 0) { - window.scrollBy(0, Math.min(-imageBottom, Header.getTopOf(file.fullImage))); - } - } - if (file.isVideo) { - return ImageExpand.setupVideo(post, Conf['Autoplay'], Conf['Show Controls']); - } - }, - setupVideo: function(post, playing, controls) { - var fullImage; - fullImage = post.file.fullImage; - if (!playing) { - fullImage.controls = controls; - return; - } - fullImage.controls = false; - $.asap((function() { - return doc.contains(fullImage); - }), function() { - if (!d.hidden && Header.isNodeVisible(fullImage)) { - return fullImage.play(); - } else { - return post.file.wasPlaying = true; - } - }); - if (controls) { - return ImageCommon.addControls(fullImage); - } - }, - videoCB: (function() { - var mousedown; - mousedown = false; - return { - mouseover: function() { - return mousedown = false; - }, - mousedown: function(e) { - if (e.button === 0) { - return mousedown = true; - } - }, - mouseup: function(e) { - if (e.button === 0) { - return mousedown = false; - } - }, - mouseout: function(e) { - if (((e.buttons & 1) || mousedown) && e.clientX <= this.getBoundingClientRect().left) { - return ImageExpand.toggle(Get.postFromNode(this)); - } - } - }; - })(), - setupVideoCB: function(post) { - var cb, eventName, ref; - ref = ImageExpand.videoCB; - for (eventName in ref) { - cb = ref[eventName]; - $.on(post.file.fullImage, eventName, cb); - } - if (post.file.videoControls) { - return $.on(post.file.videoControls.firstElementChild, 'click', function() { - return ImageExpand.toggle(post); - }); - } - }, - error: function() { - var post; - post = Get.postFromNode(this); - $.rm(this); - delete post.file.fullImage; - if (!(post.file.isExpanding || post.file.isExpanded)) { - return; - } - if (ImageCommon.decodeError(this, post.file)) { - return ImageExpand.contract(post); - } - if (ImageCommon.isFromArchive(this)) { - return ImageExpand.contract(post); - } - return ImageCommon.error(this, post, post.file, 10 * $.SECOND, function(URL) { - if (post.file.isExpanding || post.file.isExpanded) { - ImageExpand.contract(post); - if (URL) { - return ImageExpand.expand(post, URL); - } - } - }); - }, - menu: { - init: function() { - var conf, createSubEntry, el, name, ref, subEntries; - if (!ImageExpand.enabled) { - return; - } - el = $.el('span', { - textContent: 'Image Expansion', - className: 'image-expansion-link' - }); - createSubEntry = ImageExpand.menu.createSubEntry; - subEntries = []; - ref = Config.imageExpansion; - for (name in ref) { - conf = ref[name]; - subEntries.push(createSubEntry(name, conf[1])); - } - return Header.menu.addEntry({ - el: el, - order: 105, - subEntries: subEntries - }); - }, - createSubEntry: function(name, desc) { - var input, label; - label = UI.checkbox(name, name); - label.title = desc; - input = label.firstElementChild; - if (name === 'Fit width' || name === 'Fit height') { - $.on(input, 'change', ImageExpand.cb.setFitness); - } - $.event('change', null, input); - $.on(input, 'change', $.cb.checked); - return { - el: label - }; - } - } - }; - - return ImageExpand; - -}).call(this); - -ImageHost = (function() { - var ImageHost; - - ImageHost = { - init: function() { - var ref; - if (!((this.useFaster = /\S/.test(Conf['fourchanImageHost'])) && g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - return Callbacks.Post.push({ - name: 'Image Host Rewriting', - cb: this.node - }); - }, - suggestions: ['i.4cdn.org', 'is2.4chan.org'], - host: function() { - return Conf['fourchanImageHost'].trim() || 'i.4cdn.org'; - }, - flashHost: function() { - return 'i.4cdn.org'; - }, - thumbHost: function() { - return 'i.4cdn.org'; - }, - test: function(hostname) { - return hostname === 'i.4cdn.org' || ImageHost.regex.test(hostname); - }, - regex: /^is\d*\.4chan(?:nel)?\.org$/, - node: function() { - var host; - if (this.isClone) { - return; - } - host = ImageHost.host(); - if (this.file && ImageHost.test(this.file.url.split('/')[2]) && !/\.swf$/.test(this.file.url)) { - this.file.link.hostname = host; - if (this.file.thumbLink) { - this.file.thumbLink.hostname = host; - } - this.file.url = this.file.link.href; - } - return ImageHost.fixLinks($$('a', this.nodes.comment)); - }, - fixLinks: function(links) { - var host, i, len, link; - for (i = 0, len = links.length; i < len; i++) { - link = links[i]; - if (!(ImageHost.test(link.hostname) && !/\.swf$/.test(link.pathname))) { - continue; - } - host = ImageHost.host(); - if (link.hostname !== host) { - link.hostname = host; - } - } - } - }; - - return ImageHost; - -}).call(this); - -ImageHover = (function() { - var ImageHover; - - ImageHover = { - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - if (Conf['Image Hover']) { - Callbacks.Post.push({ - name: 'Image Hover', - cb: this.node - }); - } - if (Conf['Image Hover in Catalog']) { - return Callbacks.CatalogThread.push({ - name: 'Image Hover', - cb: this.catalogNode - }); - } - }, - node: function() { - var file, i, len, ref, results; - ref = this.files; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if ((file.isImage || file.isVideo) && file.thumb) { - results.push($.on(file.thumb, 'mouseover', ImageHover.mouseover(this, file))); - } - } - return results; - }, - catalogNode: function() { - var file; - file = this.thread.OP.files[0]; - if (!(file && (file.isImage || file.isVideo))) { - return; - } - return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP, file)); - }, - mouseover: function(post, file) { - return function(e) { - var base, el, error, height, isVideo, maxHeight, maxWidth, ref, ref1, scale, width, x; - if (!doc.contains(this)) { - return; - } - isVideo = file.isVideo; - if (file.isExpanding || file.isExpanded || (typeof (base = g.SITE).isThumbExpanded === "function" ? base.isThumbExpanded(file) : void 0)) { - return; - } - error = ImageHover.error(post, file); - if (((ref = ImageCommon.cache) != null ? ref.dataset.fileID : void 0) === (post.fullID + "." + file.index)) { - el = ImageCommon.popCache(); - $.on(el, 'error', error); - } else { - el = $.el((isVideo ? 'video' : 'img')); - el.dataset.fileID = post.fullID + "." + file.index; - $.on(el, 'error', error); - el.src = file.url; - } - if (Conf['Restart when Opened']) { - ImageCommon.rewind(el); - ImageCommon.rewind(this); - } - el.id = 'ihover'; - $.add(Header.hover, el); - if (isVideo) { - el.loop = true; - el.controls = false; - Volume.setup(el); - if (Conf['Autoplay']) { - el.play(); - if (this.nodeName === 'VIDEO') { - this.currentTime = el.currentTime; - } - } - } - if (file.dimensions) { - ref1 = (function() { - var i, len, ref1, results; - ref1 = file.dimensions.split('x'); - results = []; - for (i = 0, len = ref1.length; i < len; i++) { - x = ref1[i]; - results.push(+x); - } - return results; - })(), width = ref1[0], height = ref1[1]; - maxWidth = doc.clientWidth; - maxHeight = doc.clientHeight - UI.hover.padding; - scale = Math.min(1, maxWidth / width, maxHeight / height); - width *= scale; - height *= scale; - el.style.maxWidth = width + "px"; - el.style.maxHeight = height + "px"; - } - return UI.hover({ - root: this, - el: el, - latestEvent: e, - endEvents: 'mouseout click', - height: height, - width: width, - noRemove: true, - cb: function() { - $.off(el, 'error', error); - ImageCommon.pushCache(el); - ImageCommon.pause(el); - $.rm(el); - return el.removeAttribute('style'); - } - }); - }; - }, - error: function(post, file) { - return function() { - if (ImageCommon.decodeError(this, file)) { - return; - } - return ImageCommon.error(this, post, file, 3 * $.SECOND, (function(_this) { - return function(URL) { - if (URL) { - return _this.src = URL + (_this.src === URL ? '?' + Date.now() : ''); - } else { - return $.rm(_this); - } - }; - })(this)); - }; - } - }; - - return ImageHover; - -}).call(this); - -ImageLoader = (function() { - var ImageLoader, - slice = [].slice; - - ImageLoader = { - init: function() { - var el, ref, ref1, replace; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') { - return; - } - replace = Conf['Replace JPG'] || Conf['Replace PNG'] || Conf['Replace GIF'] || Conf['Replace WEBM']; - if (!(Conf['Image Prefetching'] || replace)) { - return; - } - Callbacks.Post.push({ - name: 'Image Replace', - cb: this.node - }); - $.on(d, 'PostsInserted', function() { - if (ImageLoader.prefetchEnabled || replace) { - return g.posts.forEach(ImageLoader.prefetchAll); - } - }); - if (Conf['Replace WEBM']) { - $.on(d, 'scroll visibilitychange 4chanXInitFinished PostsInserted', this.playVideos); - } - if (!(Conf['Image Prefetching'] && ((ref1 = g.VIEW) === 'index' || ref1 === 'thread'))) { - return; - } - el = $.el('a', { - href: 'javascript:;', - title: 'Prefetch Images', - className: 'fa fa-bolt disabled', - textContent: 'Prefetch' - }); - $.on(el, 'click', this.toggle); - return Header.addShortcut('prefetch', el, 525); - }, - node: function() { - var file, i, len, ref; - if (this.isClone) { - return; - } - ref = this.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (Conf['Replace WEBM'] && file.isVideo) { - ImageLoader.replaceVideo(this, file); - } - ImageLoader.prefetch(this, file); - } - }, - replaceVideo: function(post, file) { - var attr, i, len, ref, thumb, video; - thumb = file.thumb; - video = $.el('video', { - preload: 'none', - loop: true, - muted: true, - poster: thumb.src || thumb.dataset.src, - textContent: thumb.alt, - className: thumb.className - }); - video.setAttribute('muted', 'muted'); - video.dataset.md5 = thumb.dataset.md5; - ref = ['height', 'width', 'maxHeight', 'maxWidth']; - for (i = 0, len = ref.length; i < len; i++) { - attr = ref[i]; - video.style[attr] = thumb.style[attr]; - } - video.src = file.url; - $.replace(thumb, video); - file.thumb = video; - return file.videoThumb = true; - }, - prefetch: function(post, file) { - var clone, el, i, isImage, isVideo, len, ref, ref1, replace, thumb, type, url; - isImage = file.isImage, isVideo = file.isVideo, thumb = file.thumb, url = file.url; - if (file.isPrefetched || !(isImage || isVideo) || post.isHidden || post.thread.isHidden) { - return; - } - if (isVideo) { - type = 'WEBM'; - } else { - type = (ref = url.match(/\.([^.]+)$/)) != null ? ref[1].toUpperCase() : void 0; - if (type === 'JPEG') { - type = 'JPG'; - } - } - replace = Conf["Replace " + type] && !/spoiler/.test(thumb.src || thumb.dataset.src); - if (!(replace || ImageLoader.prefetchEnabled)) { - return; - } - if ($.hasClass(doc, 'catalog-mode')) { - return; - } - if (![post].concat(slice.call(post.clones)).some(function(clone) { - return doc.contains(clone.nodes.root); - })) { - return; - } - file.isPrefetched = true; - if (file.videoThumb) { - ref1 = post.clones; - for (i = 0, len = ref1.length; i < len; i++) { - clone = ref1[i]; - clone.file.thumb.preload = 'auto'; - } - thumb.preload = 'auto'; - if ($.engine === 'gecko') { - $.on(thumb, 'loadeddata', function() { - return this.removeAttribute('poster'); - }); - } - return; - } - el = $.el(isImage ? 'img' : 'video'); - if (isVideo) { - el.preload = 'auto'; - } - if (replace && isImage) { - $.on(el, 'load', function() { - var j, len1, ref2; - ref2 = post.clones; - for (j = 0, len1 = ref2.length; j < len1; j++) { - clone = ref2[j]; - clone.file.thumb.src = url; - } - return thumb.src = url; - }); - } - return el.src = url; - }, - prefetchAll: function(post) { - var file, i, len, ref; - ref = post.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - ImageLoader.prefetch(post, file); - } - }, - toggle: function() { - ImageLoader.prefetchEnabled = !ImageLoader.prefetchEnabled; - this.classList.toggle('disabled', !ImageLoader.prefetchEnabled); - if (ImageLoader.prefetchEnabled) { - g.posts.forEach(ImageLoader.prefetchAll); - } - }, - playVideos: function() { - var qpClone, ref; - qpClone = (ref = $.id('qp')) != null ? ref.firstElementChild : void 0; - return g.posts.forEach(function(post) { - var file, i, j, len, len1, ref1, ref2, thumb; - ref1 = [post].concat(slice.call(post.clones)); - for (i = 0, len = ref1.length; i < len; i++) { - post = ref1[i]; - ref2 = post.files; - for (j = 0, len1 = ref2.length; j < len1; j++) { - file = ref2[j]; - if (!file.videoThumb) { - continue; - } - thumb = file.thumb; - if (Header.isNodeVisible(thumb) || post.nodes.root === qpClone) { - thumb.play(); - } else { - thumb.pause(); - } - } - } - }); - } - }; - - return ImageLoader; - -}).call(this); - -Metadata = (function() { - var Metadata; - - Metadata = { - init: function() { - var ref; - if (!(Conf['WEBM Metadata'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - return Callbacks.Post.push({ - name: 'WEBM Metadata', - cb: this.node - }); - }, - node: function() { - var el, file, i, j, len1, ref; - ref = this.files; - for (i = j = 0, len1 = ref.length; j < len1; i = ++j) { - file = ref[i]; - if (!(/webm$/i.test(file.url))) { - continue; - } - if (this.isClone) { - el = $('.webm-title', file.text); - } else { - el = $.el('span', { - className: 'webm-title' - }); - el.dataset.index = i; - $.extend(el, {innerHTML: ""}); - $.add(file.text, [$.tn(' '), el]); - } - if (el.children.length === 1) { - $.one(el.lastElementChild, 'mouseover focus', Metadata.load); - } - } - }, - load: function() { - var index; - $.rmClass(this.parentNode, 'error'); - $.addClass(this.parentNode, 'loading'); - index = this.parentNode.dataset.index; - return CrossOrigin.binary(Get.postFromNode(this).files[+index].url, (function(_this) { - return function(data) { - var output, title; - $.rmClass(_this.parentNode, 'loading'); - if (data != null) { - title = Metadata.parse(data); - output = $.el('span', { - textContent: title || '' - }); - if (title == null) { - $.addClass(_this.parentNode, 'not-found'); - } - $.before(_this, output); - _this.parentNode.tabIndex = 0; - if (d.activeElement === _this) { - _this.parentNode.focus(); - } - return _this.tabIndex = -1; - } else { - $.addClass(_this.parentNode, 'error'); - return $.one(_this, 'click', Metadata.load); - } - }; - })(this), { - Range: 'bytes=0-9999' - }); - }, - parse: function(data) { - var element, i, readInt, size, title; - readInt = function() { - var len, n; - n = data[i++]; - len = 0; - while (n < (0x80 >> len)) { - len++; - } - n ^= 0x80 >> len; - while (len-- && i < data.length) { - n = (n << 8) ^ data[i++]; - } - return n; - }; - i = 0; - while (i < data.length) { - element = readInt(); - size = readInt(); - if (element === 0x3BA9) { - title = ''; - while (size-- && i < data.length) { - title += String.fromCharCode(data[i++]); - } - return decodeURIComponent(escape(title)); - } else if (element !== 0x8538067 && element !== 0x549A966) { - i += size; - } - } - return null; - } - }; - - return Metadata; - -}).call(this); - -RevealSpoilers = (function() { - var RevealSpoilers; - - RevealSpoilers = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Reveal Spoiler Thumbnails'])) { - return; - } - return Callbacks.Post.push({ - name: 'Reveal Spoiler Thumbnails', - cb: this.node - }); - }, - node: function() { - var file, i, len, ref, thumb; - if (this.isClone) { - return; - } - ref = this.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (!(file.thumb && file.isSpoiler)) { - continue; - } - thumb = file.thumb; - thumb.removeAttribute('style'); - thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; - if (thumb.src) { - thumb.src = file.thumbURL; - } else { - thumb.dataset.src = file.thumbURL; - } - } - } - }; - - return RevealSpoilers; - -}).call(this); - -Sauce = (function() { - var Sauce, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Sauce = { - init: function() { - var j, len, link, linkData, links, ref, ref1; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { - return; - } - $.addClass(doc, 'show-sauce'); - links = []; - ref1 = Conf['sauces'].split('\n'); - for (j = 0, len = ref1.length; j < len; j++) { - link = ref1[j]; - if (link[0] !== '#' && (linkData = this.parseLink(link))) { - links.push(linkData); - } - } - if (!links.length) { - return; - } - this.links = links; - this.link = $.el('a', { - target: '_blank', - className: 'sauce' - }); - return Callbacks.Post.push({ - name: 'Sauce', - cb: this.node - }); - }, - parseLink: function(link) { - var err, i, j, len, m, part, parts, ref, ref1, regexp; - if (!(link = link.trim())) { - return null; - } - parts = $.dict(); - ref = link.split(/;(?=(?:text|boards|types|regexp|sandbox):?)/); - for (i = j = 0, len = ref.length; j < len; i = ++j) { - part = ref[i]; - if (i === 0) { - parts['url'] = part; - } else { - m = part.match(/^(\w*):?(.*)$/); - parts[m[1]] = m[2]; - } - } - parts['text'] || (parts['text'] = ((ref1 = parts['url'].match(/(\w+)\.\w+\//)) != null ? ref1[1] : void 0) || '?'); - if ('boards' in parts) { - parts['boards'] = Filter.parseBoards(parts['boards']); - } - if ('regexp' in parts) { - try { - if ((regexp = parts['regexp'].match(/^\/(.*)\/(\w*)$/))) { - parts['regexp'] = RegExp(regexp[1], regexp[2]); - } else { - parts['regexp'] = RegExp(parts['regexp']); - } - } catch (error) { - err = error; - new Notice('warning', [$.tn("Invalid regexp for Sauce link:"), $.el('br'), $.tn(link), $.el('br'), $.tn(err.message)], 60); - return null; - } - } - return parts; - }, - createSauceLink: function(link, post, file) { - var a, base, ext, j, key, len, matches, missing, parts, ref; - ext = file.url.match(/[^.]*$/)[0]; - parts = $.dict(); - $.extend(parts, link); - if (!(!parts['boards'] || parts['boards'][post.siteID + "/" + post.boardID] || parts['boards'][post.siteID + "/*"])) { - return null; - } - if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { - return null; - } - if (!(!parts['regexp'] || (matches = file.name.match(parts['regexp'])))) { - return null; - } - missing = []; - ref = ['url', 'text']; - for (j = 0, len = ref.length; j < len; j++) { - key = ref[j]; - parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi|\$\d+)/g, function(orig, parameter) { - var type; - if (parameter[0] === '$') { - if (!matches) { - return orig; - } - type = matches[parameter.slice(1)] || ''; - } else { - type = Sauce.formatters[parameter](post, file, ext); - if (type == null) { - missing.push(parameter); - return ''; - } - } - if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { - if (/^javascript:/i.test(parts['url'])) { - type = JSON.stringify(type); - } - type = encodeURIComponent(type); - } - return type; - }); - } - if ((typeof (base = g.SITE).areMD5sDeferred === "function" ? base.areMD5sDeferred(post.board) : void 0) && missing.length && !missing.filter(function(x) { - return !/^.?MD5$/.test(x); - }).length) { - a = Sauce.link.cloneNode(false); - a.dataset.skip = '1'; - return a; - } - if (missing.length) { - return null; - } - a = Sauce.link.cloneNode(false); - a.href = parts['url']; - a.textContent = parts['text']; - if (/^javascript:/i.test(parts['url'])) { - a.removeAttribute('target'); - } - return a; - }, - node: function() { - var file, j, len, ref; - if (this.isClone) { - return; - } - ref = this.files; - for (j = 0, len = ref.length; j < len; j++) { - file = ref[j]; - Sauce.file(this, file); - } - }, - file: function(post, file) { - var j, len, link, node, nodes, observer, ref, skipped; - nodes = []; - skipped = []; - ref = Sauce.links; - for (j = 0, len = ref.length; j < len; j++) { - link = ref[j]; - if ((node = Sauce.createSauceLink(link, post, file))) { - nodes.push($.tn(' '), node); - if (node.dataset.skip) { - skipped.push([link, node]); - } - } - } - $.add(file.text, nodes); - if (skipped.length) { - observer = new MutationObserver(function() { - var k, len1, node2, ref1; - if (file.text.dataset.md5) { - for (k = 0, len1 = skipped.length; k < len1; k++) { - ref1 = skipped[k], link = ref1[0], node = ref1[1]; - if ((node2 = Sauce.createSauceLink(link, post, file))) { - $.replace(node, node2); - } - } - return observer.disconnect(); - } - }); - return observer.observe(file.text, { - attributes: true - }); - } - }, - formatters: { - TURL: function(post, file) { - return file.thumbURL; - }, - URL: function(post, file) { - return file.url; - }, - IMG: function(post, file, ext) { - if (ext === 'gif' || ext === 'jpg' || ext === 'jpeg' || ext === 'png') { - return file.url; - } else { - return file.thumbURL; - } - }, - MD5: function(post, file) { - return file.MD5; - }, - sMD5: function(post, file) { - var ref; - return (ref = file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }) : void 0; - }, - hMD5: function(post, file) { - var c; - if (file.MD5) { - return ((function() { - var j, len, ref, results; - ref = atob(file.MD5); - results = []; - for (j = 0, len = ref.length; j < len; j++) { - c = ref[j]; - results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); - } - return results; - })()).join(''); - } - }, - board: function(post) { - return post.board.ID; - }, - name: function(post, file) { - return file.name; - }, - '%': function() { - return '%'; - }, - semi: function() { - return ';'; - } - } - }; - - return Sauce; - -}).call(this); - -Volume = (function() { - var Volume; - - Volume = { - init: function() { - var base, ref, unmuteEntry, volumeEntry; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && (Conf['Image Expansion'] || Conf['Image Hover'] || Conf['Image Hover in Catalog'] || Conf['Gallery']))) { - return; - } - $.sync('Allow Sound', function(x) { - var ref1; - Conf['Allow Sound'] = x; - return (ref1 = Volume.inputs) != null ? ref1.unmute.checked = x : void 0; - }); - $.sync('Default Volume', function(x) { - var ref1; - Conf['Default Volume'] = x; - return (ref1 = Volume.inputs) != null ? ref1.volume.value = x : void 0; - }); - if (Conf['Mouse Wheel Volume']) { - Callbacks.Post.push({ - name: 'Mouse Wheel Volume', - cb: this.node - }); - } - if (typeof (base = g.SITE).noAudio === "function" ? base.noAudio(g.BOARD) : void 0) { - return; - } - if (Conf['Mouse Wheel Volume']) { - Callbacks.CatalogThread.push({ - name: 'Mouse Wheel Volume', - cb: this.catalogNode - }); - } - unmuteEntry = UI.checkbox('Allow Sound', 'Allow Sound'); - unmuteEntry.title = Config.main['Images and Videos']['Allow Sound'][1]; - volumeEntry = $.el('label', { - title: 'Default volume for videos.' - }); - $.extend(volumeEntry, {innerHTML: " Volume"}); - this.inputs = { - unmute: unmuteEntry.firstElementChild, - volume: volumeEntry.firstElementChild - }; - $.on(this.inputs.unmute, 'change', $.cb.checked); - $.on(this.inputs.volume, 'change', $.cb.value); - Header.menu.addEntry({ - el: unmuteEntry, - order: 200 - }); - return Header.menu.addEntry({ - el: volumeEntry, - order: 201 - }); - }, - setup: function(video) { - video.muted = !Conf['Allow Sound']; - video.volume = Conf['Default Volume']; - return $.on(video, 'volumechange', Volume.change); - }, - change: function() { - var items, key, muted, ref, val, volume; - ref = this, muted = ref.muted, volume = ref.volume; - items = { - 'Allow Sound': !muted, - 'Default Volume': volume - }; - for (key in items) { - val = items[key]; - if (Conf[key] === val) { - delete items[key]; - } - } - $.set(items); - $.extend(Conf, items); - if (Volume.inputs) { - Volume.inputs.unmute.checked = !muted; - return Volume.inputs.volume.value = volume; - } - }, - node: function() { - var base, file, i, len, ref; - if (typeof (base = g.SITE).noAudio === "function" ? base.noAudio(this.board) : void 0) { - return; - } - ref = this.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (!file.isVideo) { - continue; - } - if (file.thumb) { - $.on(file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - } - $.on($('.file-info', file.text) || file.link, 'wheel', Volume.wheel.bind(file.thumbLink)); - } - }, - catalogNode: function() { - var file; - file = this.thread.OP.files[0]; - if (!(file != null ? file.isVideo : void 0)) { - return; - } - return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - }, - wheel: function(e) { - var el, volume; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { - return; - } - if (!(el = $('video:not([data-md5])', this))) { - return; - } - if (el.muted || !$.hasAudio(el)) { - return; - } - volume = el.volume + 0.1; - if (e.deltaY < 0) { - volume *= 1.1; - } - if (e.deltaY > 0) { - volume /= 1.1; - } - el.volume = $.minmax(volume - 0.1, 0, 1); - return e.preventDefault(); - } - }; - - return Volume; - -}).call(this); - -Embedding = (function() { - var Embedding, - slice = [].slice; - - Embedding = { - init: function() { - var j, len, ref, ref1, type; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Linkify'] && (Conf['Embedding'] || Conf['Link Title'] || Conf['Cover Preview']))) { - return; - } - this.types = $.dict(); - ref1 = this.ordered_types; - for (j = 0, len = ref1.length; j < len; j++) { - type = ref1[j]; - this.types[type.key] = type; - } - if (Conf['Embedding'] && g.VIEW !== 'archive') { - this.dialog = UI.dialog('embedding', {innerHTML: "
    "}); - this.media = $('#media-embed', this.dialog); - $.one(d, '4chanXInitFinished', this.ready); - $.on(d, 'IndexRefreshInternal', function() { - return g.posts.forEach(function(post) { - var embed, k, l, len1, len2, ref2, ref3; - ref2 = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref2.length; k < len1; k++) { - post = ref2[k]; - ref3 = post.nodes.embedlinks; - for (l = 0, len2 = ref3.length; l < len2; l++) { - embed = ref3[l]; - Embedding.cb.catalogRemove.call(embed); - } - } - }); - }); - } - if (Conf['Link Title']) { - return $.on(d, '4chanXInitFinished PostsInserted', function() { - var key, ref2, ref3, service; - ref2 = Embedding.types; - for (key in ref2) { - service = ref2[key]; - if ((ref3 = service.title) != null ? ref3.batchSize : void 0) { - Embedding.flushTitles(service.title); - } - } - }); - } - }, - events: function(post) { - var data, el, i, items; - if (g.VIEW === 'archive') { - return; - } - if (Conf['Embedding']) { - i = 0; - items = post.nodes.embedlinks = $$('.embedder', post.nodes.comment); - while (el = items[i++]) { - $.on(el, 'click', Embedding.cb.click); - if ($.hasClass(el, 'embedded')) { - Embedding.cb.toggle.call(el); - } - } - } - if (Conf['Cover Preview']) { - i = 0; - items = $$('.linkify', post.nodes.comment); - while (el = items[i++]) { - if ((data = Embedding.services(el))) { - Embedding.preview(data); - } - } - } - }, - process: function(link, post) { - var data; - if (!(Conf['Embedding'] || Conf['Link Title'] || Conf['Cover Preview'])) { - return; - } - if ($.x('ancestor::pre', link)) { - return; - } - if (data = Embedding.services(link)) { - data.post = post; - if (Conf['Embedding'] && g.VIEW !== 'archive') { - Embedding.embed(data); - } - if (Conf['Link Title']) { - Embedding.title(data); - } - if (Conf['Cover Preview'] && g.VIEW !== 'archive') { - return Embedding.preview(data); - } - } - }, - services: function(link) { - var href, j, len, match, ref, type; - href = link.href; - ref = Embedding.ordered_types; - for (j = 0, len = ref.length; j < len; j++) { - type = ref[j]; - if ((match = type.regExp.exec(href))) { - return { - key: type.key, - uid: match[1], - options: match[2], - link: link - }; - } - } - }, - embed: function(data) { - var embed, href, key, link, name, options, post, ref, uid, value; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - href = link.href; - $.addClass(link, key.toLowerCase()); - embed = $.el('a', { - className: 'embedder', - href: 'javascript:;' - }, {innerHTML: "(unembed)"}); - ref = { - key: key, - uid: uid, - options: options, - href: href - }; - for (name in ref) { - value = ref[name]; - embed.dataset[name] = value; - } - $.on(embed, 'click', Embedding.cb.click); - $.after(link, [$.tn(' '), embed]); - post.nodes.embedlinks.push(embed); - if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote) { - if ($.hasClass(doc, 'catalog-mode')) { - return $.addClass(embed, 'embed-removed'); - } else { - return Embedding.cb.toggle.call(embed); - } - } - }, - ready: function() { - if (!Main.isThisPageLegit()) { - return; - } - $.addClass(Embedding.dialog, 'empty'); - $.on($('.close', Embedding.dialog), 'click', Embedding.closeFloat); - $.on($('.move', Embedding.dialog), 'mousedown', Embedding.dragEmbed); - $.on($('.jump', Embedding.dialog), 'click', function() { - if (doc.contains(Embedding.lastEmbed)) { - return Header.scrollTo(Embedding.lastEmbed); - } - }); - return $.add(d.body, Embedding.dialog); - }, - closeFloat: function() { - delete Embedding.lastEmbed; - $.addClass(Embedding.dialog, 'empty'); - return $.replace(Embedding.media.firstChild, $.el('div')); - }, - dragEmbed: function() { - var style; - style = Embedding.media.style; - if (Embedding.dragEmbed.mouseup) { - $.off(d, 'mouseup', Embedding.dragEmbed); - Embedding.dragEmbed.mouseup = false; - style.pointerEvents = ''; - return; - } - $.on(d, 'mouseup', Embedding.dragEmbed); - Embedding.dragEmbed.mouseup = true; - return style.pointerEvents = 'none'; - }, - title: function(data) { - var key, link, options, post, service, uid; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - if (!(service = Embedding.types[key].title)) { - return; - } - $.addClass(link, key.toLowerCase()); - if (service.batchSize) { - (service.queue || (service.queue = [])).push(data); - if (service.queue.length >= service.batchSize) { - return Embedding.flushTitles(service); - } - } else { - return CrossOrigin.cache(service.api(uid), (function() { - return Embedding.cb.title(this, data); - })); - } - }, - flushTitles: function(service) { - var cb, data, queue; - queue = service.queue; - if (!(queue != null ? queue.length : void 0)) { - return; - } - service.queue = []; - cb = function() { - var data, j, len; - for (j = 0, len = queue.length; j < len; j++) { - data = queue[j]; - Embedding.cb.title(this, data); - } - }; - return CrossOrigin.cache(service.api((function() { - var j, len, results; - results = []; - for (j = 0, len = queue.length; j < len; j++) { - data = queue[j]; - results.push(data.uid); - } - return results; - })()), cb); - }, - preview: function(data) { - var key, link, service, uid; - key = data.key, uid = data.uid, link = data.link; - if (!(service = Embedding.types[key].preview)) { - return; - } - return $.on(link, 'mouseover', function(e) { - var el, height, src; - src = service.url(uid); - height = service.height; - el = $.el('img', { - src: src, - id: 'ihover' - }); - $.add(Header.hover, el); - return UI.hover({ - root: link, - el: el, - latestEvent: e, - endEvents: 'mouseout click', - height: height - }); - }); - }, - cb: { - click: function(e) { - var div; - e.preventDefault(); - if (!$.hasClass(this, 'embedded') && (Conf['Floating Embeds'] || $.hasClass(doc, 'catalog-mode'))) { - if (!(div = Embedding.media.firstChild)) { - return; - } - $.replace(div, Embedding.cb.embed(this)); - Embedding.lastEmbed = Get.postFromNode(this).nodes.root; - return $.rmClass(Embedding.dialog, 'empty'); - } else { - return Embedding.cb.toggle.call(this); - } - }, - toggle: function() { - if ($.hasClass(this, "embedded")) { - $.rm(this.nextElementSibling); - } else { - $.after(this, Embedding.cb.embed(this)); - } - return $.toggleClass(this, 'embedded'); - }, - embed: function(a) { - var container, el, type; - container = $.el('div', { - className: 'media-embed' - }); - $.add(container, el = (type = Embedding.types[a.dataset.key]).el(a)); - el.style.cssText = type.style != null ? type.style : 'border: none; width: 640px; height: 360px;'; - return container; - }, - catalogRemove: function() { - var isCatalog; - isCatalog = $.hasClass(doc, 'catalog-mode'); - if ((isCatalog && $.hasClass(this, 'embedded')) || (!isCatalog && $.hasClass(this, 'embed-removed'))) { - Embedding.cb.toggle.call(this); - return $.toggleClass(this, 'embed-removed'); - } - }, - title: function(req, data) { - var base1, j, k, key, len, len1, link, link2, options, post, post2, ref, ref1, service, status, text, uid; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - service = Embedding.types[key].title; - status = req.status; - if ((status === 200 || status === 304) && service.status) { - status = service.status(req.response)[0]; - } - if (!status) { - return; - } - text = "[" + key + "] " + ((function() { - switch (status) { - case 200: - case 304: - text = service.text(req.response, uid); - if (typeof text === 'string') { - return text; - } else { - return text = link.textContent; - } - break; - case 404: - return "Not Found"; - case 403: - case 401: - return "Forbidden or Private"; - default: - return status + "'d"; - } - })()); - link.dataset.original = link.textContent; - link.textContent = text; - ref = post.clones; - for (j = 0, len = ref.length; j < len; j++) { - post2 = ref[j]; - ref1 = $$('a.linkify', post2.nodes.comment); - for (k = 0, len1 = ref1.length; k < len1; k++) { - link2 = ref1[k]; - if (!(link2.href === link.href)) { - continue; - } - if ((base1 = link2.dataset).original == null) { - base1.original = link2.textContent; - } - link2.textContent = text; - } - } - } - }, - ordered_types: [ - { - key: 'audio', - regExp: /^[^?#]+\.(?:mp3|m4a|oga|wav|flac)(?:[?#]|$)/i, - style: '', - el: function(a) { - return $.el('audio', { - controls: true, - preload: 'auto', - src: a.dataset.href - }); - } - }, { - key: 'image', - regExp: /^[^?#]+\.(?:gif|png|jpg|jpeg|bmp|webp)(?::\w+)?(?:[?#]|$)/i, - style: '', - el: function(a) { - return $.el('div', {innerHTML: ""}); - } - }, { - key: 'video', - regExp: /^[^?#]+\.(?:og[gv]|webm|mp4)(?:[?#]|$)/i, - style: 'max-width: 80vw; max-height: 80vh;', - el: function(a) { - var el; - el = $.el('video', { - hidden: true, - controls: true, - preload: 'auto', - src: a.dataset.href, - loop: ImageHost.test(a.dataset.href.split('/')[2]) - }); - $.on(el, 'loadedmetadata', function() { - if (el.videoHeight === 0 && el.parentNode) { - return $.replace(el, Embedding.types.audio.el(a)); - } else { - return el.hidden = false; - } - }); - return el; - } - }, { - key: 'PeerTube', - regExp: /^(\w+:\/\/[^\/]+\/videos\/watch\/\w{8}-\w{4}-\w{4}-\w{4}-\w{12})(.*)/, - el: function(a) { - var el, options, start; - options = (start = a.dataset.options.match(/[?&](start=\w+)/)) ? "?" + start[1] : ''; - el = $.el('iframe', { - src: a.dataset.uid.replace('/videos/watch/', '/videos/embed/') + options - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'BitChute', - regExp: /^\w+:\/\/(?:www\.)?bitchute\.com\/video\/([\w\-]+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://www.bitchute.com/embed/" + a.dataset.uid + "/" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Clyp', - regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w{8})/, - style: 'border: 0; width: 640px; height: 160px;', - el: function(a) { - return $.el('iframe', { - src: "https://clyp.it/" + a.dataset.uid + "/widget" - }); - }, - title: { - api: function(uid) { - return "https://api.clyp.it/oembed?url=https://clyp.it/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'Dailymotion', - regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, - el: function(a) { - var el, options, start; - options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; - el = $.el('iframe', { - src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://api.dailymotion.com/video/" + uid; - }, - text: function(_) { - return _.title; - } - }, - preview: { - url: function(uid) { - return "https://www.dailymotion.com/thumbnail/video/" + uid; - }, - height: 240 - } - }, { - key: 'Gfycat', - regExp: /^\w+:\/\/(?:www\.)?gfycat\.com\/(?:iframe\/)?(\w+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "//gfycat.com/ifr/" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Gist', - regExp: /^\w+:\/\/gist\.github\.com\/[\w\-]+\/(\w+)/, - style: '', - el: (function() { - var counter; - counter = 0; - return function(a) { - var el; - el = $.el('pre', { - hidden: true, - id: "gist-embed-" + (counter++) - }); - CrossOrigin.cache("https://api.github.com/gists/" + a.dataset.uid, function() { - el.textContent = Object.values(this.response.files)[0].content; - el.className = 'prettyprint'; - $.global(function() { - return typeof window.prettyPrint === "function" ? window.prettyPrint((function() {}), document.getElementById(document.currentScript.dataset.id).parentNode) : void 0; - }, { - id: el.id - }); - return el.hidden = false; - }); - return el; - }; - })(), - title: { - api: function(uid) { - return "https://api.github.com/gists/" + uid; - }, - text: function(arg) { - var file, files; - files = arg.files; - for (file in files) { - if (files.hasOwnProperty(file)) { - return file; - } - } - } - } - }, { - key: 'InstallGentoo', - regExp: /^\w+:\/\/paste\.installgentoo\.com\/view\/(?:raw\/|download\/|embed\/)?(\w+)/, - el: function(a) { - return $.el('iframe', { - src: "https://paste.installgentoo.com/view/embed/" + a.dataset.uid - }); - } - }, { - key: 'LiveLeak', - regExp: /^\w+:\/\/(?:\w+\.)?liveleak\.com\/.*\?.*[tif]=(\w+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://www.liveleak.com/e/" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Loopvid', - regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|m2|pc|1c|pi|ni|wl|ko|mm|ic|gc)\/[\w\-\/]+(?:,[\w\-\/]+)*|fc\/\w+\/\d+|https?:\/\/.+)/, - style: 'max-width: 80vw; max-height: 80vh;', - el: function(a) { - var _, base, el, host, j, k, l, len, len1, len2, name, names, ref, ref1, type, types, url, urls; - el = $.el('video', { - controls: true, - preload: 'auto', - loop: true - }); - if (/^http/.test(a.dataset.uid)) { - $.add(el, $.el('source', { - src: a.dataset.uid - })); - return el; - } - ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; - types = (function() { - switch (host) { - case 'gd': - case 'wu': - case 'fc': - return ['']; - case 'gc': - return ['giant', 'fat', 'zippy']; - default: - return ['.webm', '.mp4']; - } - })(); - ref1 = names.split(','); - for (j = 0, len = ref1.length; j < len; j++) { - name = ref1[j]; - for (k = 0, len1 = types.length; k < len1; k++) { - type = types[k]; - base = "" + name + type; - urls = (function() { - switch (host) { - case 'pf': - return ["https://kastden.org/_loopvid_media/pf/" + base, "https://web.archive.org/web/2/http://a.pomf.se/" + base]; - case 'kd': - return ["https://kastden.org/loopvid/" + base]; - case 'lv': - return ["https://lv.kastden.org/" + base]; - case 'gd': - return ["https://docs.google.com/uc?export=download&id=" + base]; - case 'gh': - return ["https://googledrive.com/host/" + base]; - case 'db': - return ["https://dl.dropboxusercontent.com/u/" + base]; - case 'dx': - return ["https://dl.dropboxusercontent.com/" + base]; - case 'nn': - return ["https://kastden.org/_loopvid_media/nn/" + base]; - case 'cp': - return ["https://copy.com/" + base]; - case 'wu': - return ["http://webmup.com/" + base + "/vid.webm"]; - case 'ig': - return ["https://i.imgur.com/" + base]; - case 'ky': - return ["https://kastden.org/_loopvid_media/ky/" + base]; - case 'mf': - return ["https://kastden.org/_loopvid_media/mf/" + base, "https://web.archive.org/web/2/https://d.maxfile.ro/" + base]; - case 'm2': - return ["https://kastden.org/_loopvid_media/m2/" + base]; - case 'pc': - return ["https://kastden.org/_loopvid_media/pc/" + base, "https://web.archive.org/web/2/http://a.pomf.cat/" + base]; - case '1c': - return ["http://b.1339.cf/" + base]; - case 'pi': - return ["https://kastden.org/_loopvid_media/pi/" + base, "https://web.archive.org/web/2/https://u.pomf.is/" + base]; - case 'ni': - return ["https://kastden.org/_loopvid_media/ni/" + base, "https://web.archive.org/web/2/https://u.nya.is/" + base]; - case 'wl': - return ["http://webm.land/media/" + base]; - case 'ko': - return ["https://kordy.kastden.org/loopvid/" + base]; - case 'mm': - return ["https://kastden.org/_loopvid_media/mm/" + base, "https://web.archive.org/web/2/https://my.mixtape.moe/" + base]; - case 'ic': - return ["https://media.8ch.net/file_store/" + base]; - case 'fc': - return ["//" + (ImageHost.host()) + "/" + base + ".webm"]; - case 'gc': - return ["https://" + type + ".gfycat.com/" + name + ".webm"]; - } - })(); - for (l = 0, len2 = urls.length; l < len2; l++) { - url = urls[l]; - $.add(el, $.el('source', { - src: url - })); - } - } - } - return el; - } - }, { - key: 'Openings.moe', - regExp: /^\w+:\/\/openings.moe\/\?video=([^.&=]+)/, - style: 'width: 1280px; height: 720px; max-width: 80vw; max-height: 80vh;', - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://openings.moe/?video=" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Pastebin', - regExp: /^\w+:\/\/(?:\w+\.)?pastebin\.com\/(?!u\/)(?:[\w.]+(?:\/|\?i\=))?(\w+)/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "//pastebin.com/embed_iframe.php?i=" + a.dataset.uid - }); - } - }, { - key: 'SoundCloud', - regExp: /^\w+:\/\/(?:www\.)?(?:soundcloud\.com\/|snd\.sc\/)([\w\-\/]+)/, - style: 'border: 0; width: 500px; height: 400px;', - el: function(a) { - return $.el('iframe', { - src: "https://w.soundcloud.com/player/?visual=true&show_comments=false&url=https%3A%2F%2Fsoundcloud.com%2F" + (encodeURIComponent(a.dataset.uid)) - }); - }, - title: { - api: function(uid) { - return location.protocol + "//soundcloud.com/oembed?format=json&url=https%3A%2F%2Fsoundcloud.com%2F" + (encodeURIComponent(uid)); - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'StrawPoll', - regExp: /^\w+:\/\/(?:www\.)?strawpoll\.me\/(?:embed_\d+\/)?(\d+(?:\/r)?)/, - style: 'border: 0; width: 600px; height: 406px;', - el: function(a) { - return $.el('iframe', { - src: "https://www.strawpoll.me/embed_1/" + a.dataset.uid - }); - } - }, { - key: 'Streamable', - regExp: /^\w+:\/\/(?:www\.)?streamable\.com\/(\w+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://streamable.com/o/" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://api.streamable.com/oembed?url=https://streamable.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'TwitchTV', - regExp: /^\w+:\/\/(?:www\.|secure\.|clips\.|m\.)?twitch\.tv\/(\w[^#\&\?]*)/, - el: function(a) { - var el, m, time, url; - m = a.dataset.href.match(/^\w+:\/\/(?:(clips\.)|\w+\.)?twitch\.tv\/(?:\w+\/)?(clip\/)?(\w[^#\&\?]*)/); - if (m[1] || m[2]) { - url = "//clips.twitch.tv/embed?clip=" + m[3] + "&parent=" + location.hostname; - } else { - m = a.dataset.uid.match(/(\w+)(?:\/(?:v\/)?(\d+))?/); - url = "//player.twitch.tv/?" + (m[2] ? "video=v" + m[2] : "channel=" + m[1]) + "&autoplay=false&parent=" + location.hostname; - if ((time = a.dataset.href.match(/\bt=(\w+)/))) { - url += "&time=" + time[1]; - } - } - el = $.el('iframe', { - src: url - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Twitter', - regExp: /^\w+:\/\/(?:www\.|mobile\.)?twitter\.com\/(\w+\/status\/\d+)/, - style: 'border: none; width: 550px; height: 250px; overflow: hidden; resize: both;', - el: function(a) { - var cont, el, onMessage; - el = $.el('iframe'); - $.on(el, 'load', function() { - return this.contentWindow.postMessage({ - element: 't', - query: 'height' - }, 'https://twitframe.com'); - }); - onMessage = function(e) { - if (e.source === el.contentWindow && e.origin === 'https://twitframe.com') { - $.off(window, 'message', onMessage); - return (cont || el).style.height = (+$.minmax(e.data.height, 250, 0.8 * doc.clientHeight)) + "px"; - } - }; - $.on(window, 'message', onMessage); - el.src = "https://twitframe.com/show?url=https://twitter.com/" + a.dataset.uid; - if ($.engine === 'gecko') { - el.style.cssText = 'border: none; width: 100%; height: 100%;'; - cont = $.el('div'); - $.add(cont, el); - return cont; - } else { - return el; - } - } - }, { - key: 'VidLii', - regExp: /^\w+:\/\/(?:www\.)?vidlii\.com\/watch\?v=(\w{11})/, - style: 'border: none; width: 640px; height: 392px;', - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://www.vidlii.com/embed?v=" + a.dataset.uid + "&a=0" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Vimeo', - regExp: /^\w+:\/\/(?:www\.)?vimeo\.com\/(\d+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "//player.vimeo.com/video/" + a.dataset.uid + "?wmode=opaque" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://vimeo.com/api/oembed.json?url=https://vimeo.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'Vine', - regExp: /^\w+:\/\/(?:www\.)?vine\.co\/v\/(\w+)/, - style: 'border: none; width: 500px; height: 500px;', - el: function(a) { - return $.el('iframe', { - src: "https://vine.co/v/" + a.dataset.uid + "/card" - }); - } - }, { - key: 'Vocaroo', - regExp: /^\w+:\/\/(?:(?:www\.|old\.)?vocaroo\.com|voca\.ro)\/((?:i\/)?\w+)/, - style: '', - el: function(a) { - var el; - el = $.el('iframe'); - el.width = 300; - el.height = 60; - el.setAttribute('frameborder', 0); - el.src = "https://vocaroo.com/embed/" + (a.dataset.uid.replace(/^i\//, '')) + "?autoplay=0"; - return el; - } - }, { - key: 'YouTube', - regExp: /^\w+:\/\/(?:youtu.be\/|[\w.]*youtube[\w.]*\/.*(?:v=|\bembed\/|\bv\/))([\w\-]{11})(.*)/, - el: function(a) { - var el, start; - start = a.dataset.options.match(/\b(?:star)?t\=(\w+)/); - if (start) { - start = start[1]; - } - if (start && !/^\d+$/.test(start)) { - start += ' 0h0m0s'; - start = 3600 * start.match(/(\d+)h/)[1] + 60 * start.match(/(\d+)m/)[1] + 1 * start.match(/(\d+)s/)[1]; - } - el = $.el('iframe', { - src: "//www.youtube.com/embed/" + a.dataset.uid + "?rel=0&wmode=opaque" + (start ? '&start=' + start : '') - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://www.youtube.com/oembed?url=https%3A//www.youtube.com/watch%3Fv%3D" + uid + "&format=json"; - }, - text: function(_) { - return _.title; - }, - status: function(_) { - var m; - if (_.error) { - m = _.error.match(/^(\d*)\s*(.*)/); - return [+m[1], m[2]]; - } else { - return [200, 'OK']; - } - } - }, - preview: { - url: function(uid) { - return "https://img.youtube.com/vi/" + uid + "/0.jpg"; - }, - height: 360 - } - } - ] - }; - - return Embedding; - -}).call(this); - -Linkify = (function() { - var Linkify; - - Linkify = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') || !Conf['Linkify']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - Callbacks.Post.push({ - name: 'Linkify', - cb: this.node - }); - return Embedding.init(); - }, - node: function() { - var base, j, k, len, len1, link, links, ref; - if (this.isClone) { - return Embedding.events(this); - } - if (!Linkify.regString.test(this.info.comment)) { - return; - } - ref = $$('a', this.nodes.comment); - for (j = 0, len = ref.length; j < len; j++) { - link = ref[j]; - if (!(typeof (base = g.SITE).isLinkified === "function" ? base.isLinkified(link) : void 0)) { - continue; - } - $.addClass(link, 'linkify'); - if (ImageHost.useFaster) { - ImageHost.fixLinks([link]); - } - Embedding.process(link, this); - } - links = Linkify.process(this.nodes.comment); - if (ImageHost.useFaster) { - ImageHost.fixLinks(links); - } - for (k = 0, len1 = links.length; k < len1; k++) { - link = links[k]; - Embedding.process(link, this); - } - }, - process: function(node) { - var data, end, endNode, i, index, length, links, part1, part2, ref, ref1, result, saved, snapshot, space, test, word; - test = /[^\s"]+/g; - space = /[\s"]/; - snapshot = $.X('.//br|.//text()', node); - i = 0; - links = []; - while (node = snapshot.snapshotItem(i++)) { - data = node.data; - if (!data || node.parentElement.nodeName === "A") { - continue; - } - while (result = test.exec(data)) { - index = result.index; - endNode = node; - word = result[0]; - if ((length = index + word.length) === data.length) { - test.lastIndex = 0; - while ((saved = snapshot.snapshotItem(i++))) { - if (saved.nodeName === 'BR' || (saved.parentElement.nodeName === 'P' && !saved.previousSibling)) { - if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { - continue; - } else { - break; - } - } - if (saved.parentElement.nodeName === "A" && !Linkify.regString.test(word)) { - break; - } - endNode = saved; - data = saved.data; - if (end = space.exec(data)) { - word += data.slice(0, end.index); - test.lastIndex = length = end.index; - i--; - break; - } else { - length = data.length; - word += data; - } - } - } - if (Linkify.regString.test(word)) { - links.push(Linkify.makeRange(node, endNode, index, length)); - } - if (!(test.lastIndex && node === endNode)) { - break; - } - } - } - i = links.length; - while (i--) { - links[i] = Linkify.makeLink(links[i]); - } - return links; - }, - regString: /((https?|mailto|git|magnet|ftp|irc):([a-z\d%\/?])|([-a-z\d]+[.])+(aero|asia|biz|cat|com|coop|dance|info|int|jobs|mobi|moe|museum|name|net|org|post|pro|tel|travel|xxx|xyz|edu|gov|mil|[a-z]{2})([:\/]|(?![^\s"]))|[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}|[-\w\d.@]+@[a-z\d.-]+\.[a-z\d])/i, - makeRange: function(startNode, endNode, startOffset, endOffset) { - var range; - range = document.createRange(); - range.setStart(startNode, startOffset); - range.setEnd(endNode, endOffset); - return range; - }, - makeLink: function(range) { - var a, encodedDomain, i, t, text; - text = range.toString(); - i = text.search(Linkify.regString); - if (i > 0) { - text = text.slice(i); - while (range.startOffset + i >= range.startContainer.data.length) { - i--; - } - if (i) { - range.setStart(range.startContainer, range.startOffset + i); - } - } - i = 0; - while (/[)\]}>.,]/.test(t = text.charAt(text.length - (1 + i)))) { - if (!(/[.,]/.test(t) || (text.match(/[()\[\]{}<>]/g)).length % 2)) { - break; - } - i++; - } - if (i) { - text = text.slice(0, -i); - while (range.endOffset - i < 0) { - i--; - } - if (i) { - range.setEnd(range.endContainer, range.endOffset - i); - } - } - if (!/((mailto|magnet):|.+:\/\/)/.test(text)) { - text = (/@/.test(text) ? 'mailto:' : 'http://') + text; - } - if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { - text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { - if (y === '25') { - return x; - } else { - return String.fromCharCode(parseInt(y, 16)); - } - }) + encodedDomain[2]; - } - a = $.el('a', { - className: 'linkify', - rel: 'noreferrer noopener', - target: '_blank', - href: text - }); - $.add(a, range.extractContents()); - range.insertNode(a); - return a; - } - }; - - return Linkify; - -}).call(this); - -ArchiveLink = (function() { - var ArchiveLink; - - ArchiveLink = { - init: function() { - var div, entry, i, len, ref, ref1, type; - if (!(g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Archive Link'])) { - return; - } - div = $.el('div', { - textContent: 'Archive' - }); - entry = { - el: div, - order: 60, - open: function(arg) { - var ID, board, thread; - ID = arg.ID, thread = arg.thread, board = arg.board; - return !!Redirect.to('thread', { - postID: ID, - threadID: thread.ID, - boardID: board.ID - }); - }, - subEntries: [] - }; - ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Flag', 'country'], ['Filename', 'filename'], ['Image MD5', 'MD5']]; - for (i = 0, len = ref1.length; i < len; i++) { - type = ref1[i]; - entry.subEntries.push(this.createSubEntry(type[0], type[1])); - } - return Menu.menu.addEntry(entry); - }, - createSubEntry: function(text, type) { - var el, open; - el = $.el('a', { - textContent: text, - target: '_blank' - }); - open = type === 'post' ? function(arg) { - var ID, board, thread; - ID = arg.ID, thread = arg.thread, board = arg.board; - el.href = Redirect.to('thread', { - postID: ID, - threadID: thread.ID, - boardID: board.ID - }); - return true; - } : function(post) { - var ref, typeParam, value; - typeParam = type === 'country' && post.info.flagCodeTroll ? 'troll_country' : type; - value = type === 'country' ? post.info.flagCode || ((ref = post.info.flagCodeTroll) != null ? ref.toLowerCase() : void 0) : Filter.values(type, post)[0]; - if (!value) { - return false; - } - el.href = Redirect.to('search', { - boardID: post.board.ID, - type: typeParam, - value: value, - isSearch: true - }); - return true; - }; - return { - el: el, - open: open - }; - } - }; - - return ArchiveLink; - -}).call(this); - -CopyTextLink = (function() { - var CopyTextLink; - - CopyTextLink = { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Copy Text Link'])) { - return; - } - a = $.el('a', { - className: 'copy-text-link', - href: 'javascript:;', - textContent: 'Copy Text' - }); - $.on(a, 'click', CopyTextLink.copy); - return Menu.menu.addEntry({ - el: a, - order: 12, - open: function(post) { - CopyTextLink.text = (post.origin || post).commentOrig(); - return true; - } - }); - }, - copy: function() { - var el; - el = $.el('textarea', { - className: 'copy-text-element', - value: CopyTextLink.text - }); - $.add(d.body, el); - el.select(); - try { - d.execCommand('copy'); - } catch (error) {} - return $.rm(el); - } - }; - - return CopyTextLink; - -}).call(this); - -DeleteLink = (function() { - var DeleteLink; - - DeleteLink = { - auto: [$.dict(), $.dict()], - init: function() { - var div, fileEl, fileEntry, postEl, postEntry, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Delete Link'])) { - return; - } - div = $.el('div', { - className: 'delete-link', - textContent: 'Delete' - }); - postEl = $.el('a', { - className: 'delete-post', - href: 'javascript:;' - }); - fileEl = $.el('a', { - className: 'delete-file', - href: 'javascript:;' - }); - this.nodes = { - menu: div.firstChild, - links: [postEl, fileEl] - }; - postEntry = { - el: postEl, - open: function() { - postEl.textContent = DeleteLink.linkText(false); - $.on(postEl, 'click', DeleteLink.toggle); - return true; - } - }; - fileEntry = { - el: fileEl, - open: function(arg) { - var file; - file = arg.file; - if (!file || file.isDead) { - return false; - } - fileEl.textContent = DeleteLink.linkText(true); - $.on(fileEl, 'click', DeleteLink.toggle); - return true; - } - }; - return Menu.menu.addEntry({ - el: div, - order: 40, - open: function(post) { - if (post.isDead) { - return false; - } - DeleteLink.post = post; - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - DeleteLink.cooldown.start(post); - return true; - }, - subEntries: [postEntry, fileEntry] - }); - }, - menuText: function() { - var seconds; - if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { - return "Delete (" + seconds + ")"; - } else { - return 'Delete'; - } - }, - linkText: function(fileOnly) { - var text; - text = fileOnly ? 'File' : 'Post'; - if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { - text = "Deleting " + (text.toLowerCase()) + "..."; - } - return text; - }, - toggle: function() { - var auto, fileOnly, post; - post = DeleteLink.post; - fileOnly = $.hasClass(this, 'delete-file'); - auto = DeleteLink.auto[+fileOnly]; - if (auto[post.fullID]) { - delete auto[post.fullID]; - } else { - auto[post.fullID] = true; - } - this.textContent = DeleteLink.linkText(fileOnly); - if (!DeleteLink.cooldown.seconds[post.fullID]) { - return DeleteLink["delete"](post, fileOnly); - } - }, - "delete": function(post, fileOnly) { - var form, link; - link = DeleteLink.nodes.links[+fileOnly]; - delete DeleteLink.auto[+fileOnly][post.fullID]; - if (post.fullID === DeleteLink.post.fullID) { - $.off(link, 'click', DeleteLink.toggle); - } - form = { - mode: 'usrdel', - onlyimgdel: fileOnly, - pwd: QR.persona.getPassword() - }; - form[+post.ID] = 'delete'; - return $.ajax($.id('delform').action.replace("/" + g.BOARD + "/", "/" + post.board + "/"), { - responseType: 'document', - withCredentials: true, - onloadend: function() { - return DeleteLink.load(link, post, fileOnly, this.response); - }, - form: $.formData(form) - }); - }, - load: function(link, post, fileOnly, resDoc) { - var el, msg; - if (!resDoc) { - new Notice('warning', 'Connection error, please retry.', 20); - if (post.fullID === DeleteLink.post.fullID) { - $.on(link, 'click', DeleteLink.toggle); - } - return; - } - link.textContent = DeleteLink.linkText(fileOnly); - if (resDoc.title === '4chan - Banned') { - el = $.el('span', {innerHTML: "You can't delete posts because you are banned."}); - return new Notice('warning', el, 20); - } else if (msg = resDoc.getElementById('errmsg')) { - new Notice('warning', msg.textContent, 20); - if (post.fullID === DeleteLink.post.fullID) { - $.on(link, 'click', DeleteLink.toggle); - } - if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { - DeleteLink.cooldown.start(post, 5); - DeleteLink.auto[+fileOnly][post.fullID] = true; - return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); - } - } else { - if (!fileOnly) { - QR.cooldown["delete"](post); - } - if (resDoc.title === 'Updating index...') { - (post.origin || post).kill(fileOnly); - } - if (post.fullID === DeleteLink.post.fullID) { - return link.textContent = 'Deleted'; - } - } - }, - cooldown: { - seconds: $.dict(), - start: function(post, seconds) { - if (DeleteLink.cooldown.seconds[post.fullID] != null) { - return; - } - if (seconds == null) { - seconds = QR.cooldown.secondsDeletion(post); - } - if (seconds > 0) { - DeleteLink.cooldown.seconds[post.fullID] = seconds; - return DeleteLink.cooldown.count(post); - } - }, - count: function(post) { - var fileOnly, i, len, ref; - if (post.fullID === DeleteLink.post.fullID) { - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - } - if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { - DeleteLink.cooldown.seconds[post.fullID]--; - setTimeout(DeleteLink.cooldown.count, 1000, post); - } else { - delete DeleteLink.cooldown.seconds[post.fullID]; - ref = [false, true]; - for (i = 0, len = ref.length; i < len; i++) { - fileOnly = ref[i]; - if (DeleteLink.auto[+fileOnly][post.fullID]) { - DeleteLink["delete"](post, fileOnly); - } - } - } - } - } - }; - - return DeleteLink; - -}).call(this); - -DownloadLink = (function() { - var DownloadLink; - - DownloadLink = { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Download Link'])) { - return; - } - a = $.el('a', { - className: 'download-link', - textContent: 'Download file' - }); - $.on(a, 'click', ImageCommon.download); - return Menu.menu.addEntry({ - el: a, - order: 100, - open: function(arg) { - var file; - file = arg.file; - if (!file) { - return false; - } - a.href = file.url; - a.download = file.name; - return true; - } - }); - } - }; - - return DownloadLink; - -}).call(this); - -Menu = (function() { - var Menu; - - Menu = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'])) { - return; - } - this.button = $.el('a', { - className: 'menu-button', - href: 'javascript:;' - }); - $.extend(this.button, {innerHTML: ""}); - this.menu = new UI.Menu('post'); - Callbacks.Post.push({ - name: 'Menu', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Menu', - cb: this.catalogNode - }); - }, - node: function() { - var button; - if (this.isClone) { - button = $('.menu-button', this.nodes.info); - $.rmClass(button, 'active'); - $.rm($('.dialog', this.nodes.info)); - Menu.makeButton(this, button); - return; - } - return $.add(this.nodes.info, Menu.makeButton(this)); - }, - catalogNode: function() { - return $.after(this.nodes.icons, Menu.makeButton(this.thread.OP)); - }, - makeButton: function(post, button) { - button || (button = Menu.button.cloneNode(true)); - $.on(button, 'click', function(e) { - return Menu.menu.toggle(e, this, post); - }); - return button; - } - }; - - return Menu; - -}).call(this); - -ReportLink = (function() { - var ReportLink; - - ReportLink = { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Report Link'])) { - return; - } - a = $.el('a', { - className: 'report-link', - href: 'javascript:;', - textContent: 'Report' - }); - $.on(a, 'click', ReportLink.report); - return Menu.menu.addEntry({ - el: a, - order: 10, - open: function(post) { - ReportLink.url = "//sys." + (location.hostname.split('.')[1]) + ".org/" + post.board + "/imgboard.php?mode=report&no=" + post; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - ReportLink.dims = 'width=350,height=275'; - } else { - ReportLink.dims = 'width=400,height=550'; - } - return true; - } - }); - }, - report: function() { - var dims, id, set, url; - url = ReportLink.url, dims = ReportLink.dims; - id = Date.now(); - set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; - return window.open(url, id, set); - } - }; - - return ReportLink; - -}).call(this); - -AntiAutoplay = (function() { - var AntiAutoplay; - - AntiAutoplay = { - init: function() { - var audio, i, len, ref; - if (!Conf['Disable Autoplaying Sounds']) { - return; - } - $.addClass(doc, 'anti-autoplay'); - ref = $$('audio[autoplay]', doc); - for (i = 0, len = ref.length; i < len; i++) { - audio = ref[i]; - this.stop(audio); - } - window.addEventListener('loadstart', ((function(_this) { - return function(e) { - return _this.stop(e.target); - }; - })(this)), true); - Callbacks.Post.push({ - name: 'Disable Autoplaying Sounds', - cb: this.node - }); - return $.ready((function(_this) { - return function() { - return _this.process(d.body); - }; - })(this)); - }, - stop: function(audio) { - if (!audio.autoplay) { - return; - } - audio.pause(); - audio.autoplay = false; - if (audio.controls) { - return; - } - audio.controls = true; - return $.addClass(audio, 'controls-added'); - }, - node: function() { - return AntiAutoplay.process(this.nodes.comment); - }, - process: function(root) { - var i, iframe, j, len, len1, object, ref, ref1; - ref = $$('iframe[src*="youtube"][src*="autoplay=1"]', root); - for (i = 0, len = ref.length; i < len; i++) { - iframe = ref[i]; - AntiAutoplay.processVideo(iframe, 'src'); - } - ref1 = $$('object[data*="youtube"][data*="autoplay=1"]', root); - for (j = 0, len1 = ref1.length; j < len1; j++) { - object = ref1[j]; - AntiAutoplay.processVideo(object, 'data'); - } - }, - processVideo: function(el, attr) { - el[attr] = el[attr].replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - if (window.getComputedStyle(el).display === 'none') { - el.style.display = 'block'; - } - return $.addClass(el, 'autoplay-removed'); - } - }; - - return AntiAutoplay; - -}).call(this); - -Banner = (function() { - var Banner, - slice = [].slice; - - Banner = { - init: function() { - if (Conf['Custom Board Titles']) { - this.db = new DataBoard('customTitles', null, true); - } - $.asap((function() { - return d.body; - }), function() { - return $.asap((function() { - return $('hr'); - }), Banner.ready); - }); - if (g.BOARD.ID !== 'f') { - return Main.ready(function() { - return $.queueTask(Banner.load); - }); - } - }, - ready: function() { - var banner, children; - banner = $(".boardBanner"); - children = banner.children; - if (g.VIEW === 'thread' && Conf['Remove Thread Excerpt']) { - Banner.setTitle(children[1].textContent); - } - children[0].title = "Click to change"; - $.on(children[0], 'click', Banner.cb.toggle); - if (Conf['Custom Board Titles']) { - Banner.custom(children[1]); - if (children[2]) { - return Banner.custom(children[2]); - } - } - }, - load: function() { - var bannerCnt, img; - bannerCnt = $.id('bannerCnt'); - if (!bannerCnt.firstChild) { - img = $.el('img', { - alt: '4chan', - src: '//s.4cdn.org/image/title/' + bannerCnt.dataset.src - }); - return $.add(bannerCnt, img); - } - }, - setTitle: function(title) { - if (Unread.title != null) { - Unread.title = title; - return Unread.update(); - } else { - return d.title = title; - } - }, - cb: { - toggle: function() { - var banner, i, ref; - if (!((ref = Banner.choices) != null ? ref.length : void 0)) { - Banner.choices = Conf['knownBanners'].split(',').slice(); - } - i = Math.floor(Banner.choices.length * Math.random()); - banner = Banner.choices.splice(i, 1); - return $('img', this.parentNode).src = "//s.4cdn.org/image/title/" + banner; - }, - click: function(e) { - var base, br, j, len, name, ref; - if (!(e.ctrlKey || e.metaKey)) { - return; - } - if ((base = Banner.original)[name = this.className] == null) { - base[name] = this.cloneNode(true); - } - this.contentEditable = true; - ref = $$('br', this); - for (j = 0, len = ref.length; j < len; j++) { - br = ref[j]; - $.replace(br, $.tn('\n')); - } - return this.focus(); - }, - keydown: function(e) { - e.stopPropagation(); - if (!e.shiftKey && e.keyCode === 13) { - return this.blur(); - } - }, - blur: function() { - var br, j, len, ref; - ref = $$('br', this); - for (j = 0, len = ref.length; j < len; j++) { - br = ref[j]; - $.replace(br, $.tn('\n')); - } - if (this.textContent = this.textContent.replace(/\n*$/, '')) { - this.contentEditable = false; - return Banner.db.set({ - boardID: g.BOARD.ID, - threadID: this.className, - val: { - title: this.textContent, - orig: Banner.original[this.className].textContent - } - }); - } else { - $.rmAll(this); - $.add(this, slice.call(Banner.original[this.className].cloneNode(true).childNodes)); - return Banner.db["delete"]({ - boardID: g.BOARD.ID, - threadID: this.className - }); - } - } - }, - original: $.dict(), - custom: function(child) { - var className, data, event, j, len, ref; - className = child.className; - child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); - child.spellcheck = false; - ref = ['click', 'keydown', 'blur']; - for (j = 0, len = ref.length; j < len; j++) { - event = ref[j]; - $.on(child, event, Banner.cb[event]); - } - if (data = Banner.db.get({ - boardID: g.BOARD.ID, - threadID: className - })) { - if (Conf['Persistent Custom Board Titles'] || data.orig === child.textContent) { - Banner.original[className] = child.cloneNode(true); - return child.textContent = data.title; - } else { - return Banner.db["delete"]({ - boardID: g.BOARD.ID, - threadID: className - }); - } - } - } - }; - - return Banner; - -}).call(this); - -CatalogLinks = (function() { - var CatalogLinks; - - CatalogLinks = { - init: function() { - var el, input, selector; - if (g.SITE.software === 'yotsuba' && (Conf['External Catalog'] || Conf['JSON Index']) && !(Conf['JSON Index'] && g.VIEW === 'index')) { - selector = (function() { - switch (g.VIEW) { - case 'thread': - case 'archive': - return '.navLinks.desktop > a'; - case 'catalog': - return '.navLinks > :first-child > a'; - case 'index': - return '#ctrl-top > a, .cataloglink > a'; - } - })(); - $.ready(function() { - var base, catalogLink, catalogURL, i, len, link, link2, ref; - ref = $$(selector); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - switch (link.pathname.replace(/\/+/g, '/')) { - case "/" + g.BOARD + "/": - if (Conf['JSON Index']) { - link.textContent = 'Index'; - } - link.href = CatalogLinks.index(); - break; - case "/" + g.BOARD + "/catalog": - link.href = CatalogLinks.catalog(); - } - if (g.VIEW === 'catalog' && (catalogURL = CatalogLinks.catalog()) !== (typeof (base = g.SITE.urls).catalog === "function" ? base.catalog(g.BOARD) : void 0)) { - catalogLink = link.parentNode.cloneNode(true); - link2 = catalogLink.firstElementChild; - link2.href = catalogURL; - link2.textContent = link2.hostname === location.hostname ? '4chan X Catalog' : 'External Catalog'; - $.after(link.parentNode, [$.tn(' '), catalogLink]); - } - } - }); - } - if (g.SITE.software === 'yotsuba' && Conf['JSON Index'] && Conf['Use 4chan X Catalog']) { - Callbacks.Post.push({ - name: 'Catalog Link Rewrite', - cb: this.node - }); - } - if ((this.enabled = Conf['Catalog Links'])) { - CatalogLinks.el = el = UI.checkbox('Header catalog links', 'Catalog Links'); - el.id = 'toggleCatalog'; - input = $('input', el); - $.on(input, 'change', this.toggle); - $.sync('Header catalog links', CatalogLinks.set); - return Header.menu.addEntry({ - el: el, - order: 95 - }); - } - }, - node: function() { - var a, i, len, m, ref; - ref = $$('a', this.nodes.comment); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - if (m = a.href.match(/^https?:\/\/(boards\.4chan(?:nel)?\.org\/[^\/]+)\/catalog(#s=.*)?/)) { - a.href = "//" + m[1] + "/" + (m[2] || '#catalog'); - } - } - }, - toggle: function() { - $.event('CloseMenu'); - $.set('Header catalog links', this.checked); - return CatalogLinks.set(this.checked); - }, - set: function(useCatalog) { - Conf['Header catalog links'] = useCatalog; - CatalogLinks.setLinks(Header.boardList); - CatalogLinks.setLinks(Header.bottomBoardList); - CatalogLinks.el.title = "Turn catalog links " + (useCatalog ? 'off' : 'on') + "."; - return $('input', CatalogLinks.el).checked = useCatalog; - }, - setLinks: function(list) { - var VIEW, a, board, boardID, i, len, ref, ref1, ref2, ref3, siteID, tail, url; - if (!(((ref = CatalogLinks.enabled) != null ? ref : Conf['Catalog Links']) && list)) { - return; - } - tail = /(?:index)?(?:\.\w+)?$/; - ref1 = $$('a:not([data-only])', list); - for (i = 0, len = ref1.length; i < len; i++) { - a = ref1[i]; - ref2 = a.dataset, siteID = ref2.siteID, boardID = ref2.boardID; - if (!(siteID && boardID)) { - ref3 = Site.parseURL(a), siteID = ref3.siteID, boardID = ref3.boardID, VIEW = ref3.VIEW; - if (!(siteID && boardID && (VIEW === 'index' || VIEW === 'catalog') && (a.dataset.indexOptions || a.href.replace(tail, '') === (Get.url(VIEW, { - siteID: siteID, - boardID: boardID - }) || '').replace(tail, '')))) { - continue; - } - $.extend(a.dataset, { - siteID: siteID, - boardID: boardID - }); - } - board = { - siteID: siteID, - boardID: boardID - }; - url = Conf['Header catalog links'] ? CatalogLinks.catalog(board) : Get.url('index', board); - if (url) { - a.href = url; - if (a.dataset.indexOptions && url.split('#')[0] === Get.url('index', board)) { - a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; - } - } - } - }, - externalParse: function() { - var board, boards, excludes, i, len, line, ref, ref1, ref2, url; - CatalogLinks.externalList = $.dict(); - ref = Conf['externalCatalogURLs'].split('\n'); - for (i = 0, len = ref.length; i < len; i++) { - line = ref[i]; - if (line[0] === '#') { - continue; - } - url = line.split(';')[0]; - boards = Filter.parseBoards(((ref1 = line.match(/;boards:([^;]+)/)) != null ? ref1[1] : void 0) || '*'); - excludes = Filter.parseBoards((ref2 = line.match(/;exclude:([^;]+)/)) != null ? ref2[1] : void 0) || $.dict(); - for (board in boards) { - if (!(excludes[board] || excludes[board.split('/')[0] + '/*'])) { - CatalogLinks.externalList[board] = url; - } - } - } - }, - external: function(arg) { - var boardID, external, siteID; - siteID = arg.siteID, boardID = arg.boardID; - if (!CatalogLinks.externalList) { - CatalogLinks.externalParse(); - } - external = CatalogLinks.externalList[siteID + "/" + boardID] || CatalogLinks.externalList[siteID + "/*"]; - if (external) { - return external.replace(/%board/g, boardID); - } else { - return void 0; - } - }, - jsonIndex: function(board, hash) { - if (g.SITE.ID === board.siteID && g.BOARD.ID === board.boardID && g.VIEW === 'index') { - return hash; - } else { - return Get.url('index', board) + hash; - } - }, - catalog: function(board) { - var external, nativeCatalog; - if (board == null) { - board = g.BOARD; - } - if (Conf['External Catalog'] && (external = CatalogLinks.external(board))) { - return external; - } else if (Index.enabledOn(board) && Conf['Use 4chan X Catalog']) { - return CatalogLinks.jsonIndex(board, '#catalog'); - } else if ((nativeCatalog = Get.url('catalog', board))) { - return nativeCatalog; - } else { - return CatalogLinks.external(board); - } - }, - index: function(board) { - if (board == null) { - board = g.BOARD; - } - if (Index.enabledOn(board)) { - return CatalogLinks.jsonIndex(board, '#index'); - } else { - return Get.url('index', board); - } - } - }; - - return CatalogLinks; - -}).call(this); - -CustomCSS = (function() { - var CustomCSS; - - CustomCSS = { - init: function() { - if (!Conf['Custom CSS']) { - return; - } - return this.addStyle(); - }, - addStyle: function() { - return this.style = $.addStyle(CSS.sub(Conf['usercss']), 'custom-css', '#fourchanx-css'); - }, - rmStyle: function() { - if (this.style) { - $.rm(this.style); - return delete this.style; - } - }, - update: function() { - if (!this.style) { - return this.addStyle(); - } - return this.style.textContent = CSS.sub(Conf['usercss']); - } - }; - - return CustomCSS; - -}).call(this); - -ExpandComment = (function() { - var ExpandComment; - - ExpandComment = { - init: function() { - if (g.VIEW !== 'index' || !Conf['Comment Expansion'] || Conf['JSON Index']) { - return; - } - return Callbacks.Post.push({ - name: 'Comment Expansion', - cb: this.node - }); - }, - node: function() { - var a; - if (a = $('.abbr > a:not([onclick])', this.nodes.comment)) { - return $.on(a, 'click', ExpandComment.cb); - } - }, - callbacks: [], - cb: function(e) { - e.preventDefault(); - return ExpandComment.expand(Get.postFromNode(this)); - }, - expand: function(post) { - var a; - if (post.nodes.longComment && !post.nodes.longComment.parentNode) { - $.replace(post.nodes.shortComment, post.nodes.longComment); - post.nodes.comment = post.nodes.longComment; - return; - } - if (!(a = $('.abbr > a', post.nodes.comment))) { - return; - } - a.textContent = "Post No." + post + " Loading..."; - return $.cache(g.SITE.urls.threadJSON({ - boardID: post.boardID, - threadID: post.threadID - }), function() { - return ExpandComment.parse(this, a, post); - }); - }, - contract: function(post) { - var a; - if (!post.nodes.shortComment) { - return; - } - a = $('.abbr > a', post.nodes.shortComment); - a.textContent = 'here'; - $.replace(post.nodes.longComment, post.nodes.shortComment); - return post.nodes.comment = post.nodes.shortComment; - }, - parse: function(req, a, post) { - var callback, clone, comment, href, i, j, k, len, len1, len2, postObj, posts, quote, ref, ref1, spoilerRange, status; - status = req.status; - if (status !== 200 && status !== 304) { - a.textContent = status ? "Error " + req.statusText + " (" + status + ")" : 'Connection Error'; - return; - } - posts = req.response.posts; - if (spoilerRange = posts[0].custom_spoiler) { - g.SITE.Build.spoilerRange[g.BOARD] = spoilerRange; - } - for (i = 0, len = posts.length; i < len; i++) { - postObj = posts[i]; - if (postObj.no === post.ID) { - break; - } - } - if (postObj.no !== post.ID) { - a.textContent = "Post No." + post + " not found."; - return; - } - comment = post.nodes.comment; - clone = comment.cloneNode(false); - clone.innerHTML = postObj.com; - ref = $$('.quotelink', clone); - for (j = 0, len1 = ref.length; j < len1; j++) { - quote = ref[j]; - href = quote.getAttribute('href'); - if (href[0] === '/') { - continue; - } - if (href[0] === '#') { - quote.href = "" + (a.pathname.split(/\/+/).splice(0, 4).join('/')) + href; - } else { - quote.href = (a.pathname.split(/\/+/).splice(0, 3).join('/')) + "/" + href; - } - } - post.nodes.shortComment = comment; - $.replace(comment, clone); - post.nodes.comment = post.nodes.longComment = clone; - post.parseComment(); - post.parseQuotes(); - ref1 = ExpandComment.callbacks; - for (k = 0, len2 = ref1.length; k < len2; k++) { - callback = ref1[k]; - callback.call(post); - } - } - }; - - return ExpandComment; - -}).call(this); - -ExpandThread = (function() { - var ExpandThread, - slice = [].slice; - - ExpandThread = { - statuses: $.dict(), - init: function() { - if (!(g.VIEW === 'index' && Conf['Thread Expansion'])) { - return; - } - if (Conf['JSON Index']) { - return $.on(d, 'IndexRefreshInternal', this.onIndexRefresh); - } else { - return Callbacks.Thread.push({ - name: 'Expand Thread', - cb: function() { - return ExpandThread.setButton(this); - } - }); - } - }, - setButton: function(thread) { - var a, ref; - if (!(thread.nodes.root && (a = $('.summary', thread.nodes.root)))) { - return; - } - a.textContent = (ref = g.SITE.Build).summaryText.apply(ref, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - a.style.cursor = 'pointer'; - return $.on(a, 'click', ExpandThread.cbToggle); - }, - disconnect: function(refresh) { - var oldReq, ref, status, threadID; - if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { - return; - } - ref = ExpandThread.statuses; - for (threadID in ref) { - status = ref[threadID]; - if ((oldReq = status.req)) { - delete status.req; - oldReq.abort(); - } - delete ExpandThread.statuses[threadID]; - } - if (!refresh) { - return $.off(d, 'IndexRefreshInternal', this.onIndexRefresh); - } - }, - onIndexRefresh: function() { - ExpandThread.disconnect(true); - return g.BOARD.threads.forEach(function(thread) { - return ExpandThread.setButton(thread); - }); - }, - cbToggle: function(e) { - if ($.modifiedClick(e)) { - return; - } - e.preventDefault(); - return ExpandThread.toggle(Get.threadFromNode(this)); - }, - cbToggleBottom: function(e) { - var bottom, thread; - if ($.modifiedClick(e)) { - return; - } - e.preventDefault(); - thread = Get.threadFromNode(this); - $.rm(this); - bottom = thread.nodes.root.getBoundingClientRect().bottom; - ExpandThread.toggle(thread); - return window.scrollBy(0, thread.nodes.root.getBoundingClientRect().bottom - bottom); - }, - toggle: function(thread) { - var a; - if (!(thread.nodes.root && (a = $('.summary', thread.nodes.root)))) { - return; - } - if (thread.ID in ExpandThread.statuses) { - return ExpandThread.contract(thread, a, thread.nodes.root); - } else { - return ExpandThread.expand(thread, a); - } - }, - expand: function(thread, a) { - var ref, status; - ExpandThread.statuses[thread] = status = {}; - a.textContent = (ref = g.SITE.Build).summaryText.apply(ref, ['...'].concat(slice.call(a.textContent.match(/\d+/g)))); - status.req = $.cache(g.SITE.urls.threadJSON({ - boardID: thread.board.ID, - threadID: thread.ID - }), function() { - if (this !== status.req) { - return; - } - delete status.req; - return ExpandThread.parse(this, thread, a); - }); - return status.numReplies = $$(g.SITE.selectors.replyOriginal, thread.nodes.root).length; - }, - contract: function(thread, a, threadRoot) { - var filesCount, i, inlined, len, oldReq, postsCount, ref, replies, reply, status; - status = ExpandThread.statuses[thread]; - delete ExpandThread.statuses[thread]; - if ((oldReq = status.req)) { - delete status.req; - oldReq.abort(); - if (a) { - a.textContent = (ref = g.SITE.Build).summaryText.apply(ref, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - } - return; - } - replies = $$('.thread > .replyContainer', threadRoot); - if (status.numReplies) { - replies = replies.slice(0, -status.numReplies); - } - postsCount = 0; - filesCount = 0; - for (i = 0, len = replies.length; i < len; i++) { - reply = replies[i]; - if (Conf['Quote Inlining']) { - while (inlined = $('.inlined', reply)) { - inlined.click(); - } - } - postsCount++; - if ('file' in Get.postFromRoot(reply)) { - filesCount++; - } - $.rm(reply); - } - if (Index.enabled) { - $.event('PostsRemoved', null, a.parentNode); - } - a.textContent = g.SITE.Build.summaryText('+', postsCount, filesCount); - return $.rm($('.summary-bottom', threadRoot)); - }, - parse: function(req, thread, a) { - var a2, filesCount, i, len, post, postData, posts, postsCount, postsRoot, ref, ref1, root; - if ((ref = req.status) !== 200 && ref !== 304) { - a.textContent = req.status ? "Error " + req.statusText + " (" + req.status + ")" : 'Connection Error'; - return; - } - g.SITE.Build.spoilerRange[thread.board] = req.response.posts[0].custom_spoiler; - posts = []; - postsRoot = []; - filesCount = 0; - ref1 = req.response.posts; - for (i = 0, len = ref1.length; i < len; i++) { - postData = ref1[i]; - if (postData.no === thread.ID) { - continue; - } - if ((post = thread.posts.get(postData.no)) && !post.isFetchedQuote) { - if ('file' in post) { - filesCount++; - } - root = post.nodes.root; - postsRoot.push(root); - continue; - } - root = g.SITE.Build.postFromObject(postData, thread.board.ID); - post = new Post(root, thread, thread.board); - if ('file' in post) { - filesCount++; - } - posts.push(post); - postsRoot.push(root); - } - Main.callbackNodes('Post', posts); - $.after(a, postsRoot); - $.event('PostsInserted', null, a.parentNode); - postsCount = postsRoot.length; - a.textContent = g.SITE.Build.summaryText('-', postsCount, filesCount); - if (root) { - a2 = a.cloneNode(true); - a2.classList.add('summary-bottom'); - $.on(a2, 'click', ExpandThread.cbToggleBottom); - return $.after(root, a2); - } - } - }; - - return ExpandThread; - -}).call(this); - -FileInfo = (function() { - var FileInfo; - - FileInfo = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') || !Conf['File Info Formatting']) { - return; - } - return Callbacks.Post.push({ - name: 'File Info Formatting', - cb: this.node - }); - }, - node: function() { - var a, i, info, j, len, len1, oldInfo, ref, ref1; - if (!this.file) { - return; - } - if (this.isClone) { - ref = $$('.file-info .download-button', this.file.text); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - $.on(a, 'click', ImageCommon.download); - } - ref1 = $$('.file-info .quick-filter-md5', this.file.text); - for (j = 0, len1 = ref1.length; j < len1; j++) { - a = ref1[j]; - $.on(a, 'click', Filter.quickFilterMD5); - } - return; - } - oldInfo = $.el('span', { - className: 'fileText-original' - }); - $.prepend(this.file.link.parentNode, oldInfo); - $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); - info = $.el('span', { - className: 'file-info' - }); - FileInfo.format(Conf['fileInfo'], this, info); - return $.prepend(this.file.text, info); - }, - format: function(formatString, post, outputNode) { - var a, i, j, len, len1, output, ref, ref1; - output = []; - formatString.replace(/%(.)|[^%]+/g, function(s, c) { - output.push($.hasOwn(FileInfo.formatters, c) ? FileInfo.formatters[c].call(post) : {innerHTML: E(s)}); - return ''; - }); - $.extend(outputNode, {innerHTML: E.cat(output)}); - ref = $$('.download-button', outputNode); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - $.on(a, 'click', ImageCommon.download); - } - ref1 = $$('.quick-filter-md5', outputNode); - for (j = 0, len1 = ref1.length; j < len1; j++) { - a = ref1[j]; - $.on(a, 'click', Filter.quickFilterMD5); - } - }, - formatters: { - t: function() { - return {innerHTML: E(this.file.url.match(/[^/]*$/)[0])}; - }, - T: function() { - return {innerHTML: "" + (FileInfo.formatters.t.call(this)).innerHTML + ""}; - }, - l: function() { - return {innerHTML: "" + (FileInfo.formatters.n.call(this)).innerHTML + ""}; - }, - L: function() { - return {innerHTML: "" + (FileInfo.formatters.N.call(this)).innerHTML + ""}; - }, - n: function() { - var fullname, shortname; - fullname = this.file.name; - shortname = SW.yotsuba.Build.shortFilename(this.file.name, this.isReply); - if (fullname === shortname) { - return {innerHTML: E(fullname)}; - } else { - return {innerHTML: "" + E(shortname) + "" + E(fullname) + ""}; - } - }, - N: function() { - return {innerHTML: E(this.file.name)}; - }, - d: function() { - return {innerHTML: ""}; - }, - f: function() { - return {innerHTML: ""}; - }, - p: function() { - return {innerHTML: ((this.file.isSpoiler) ? "Spoiler, " : "")}; - }, - s: function() { - return {innerHTML: E(this.file.size)}; - }, - B: function() { - return {innerHTML: E(Math.round(this.file.sizeInBytes)) + " Bytes"}; - }, - K: function() { - return {innerHTML: E(Math.round(this.file.sizeInBytes/1024)) + " KB"}; - }, - M: function() { - return {innerHTML: E(Math.round(this.file.sizeInBytes/1048576*100)/100) + " MB"}; - }, - r: function() { - return {innerHTML: E(this.file.dimensions || "PDF")}; - }, - g: function() { - return {innerHTML: ((this.file.tag) ? ", " + E(this.file.tag) : "")}; - }, - '%': function() { - return {innerHTML: "%"}; - } - } - }; - - return FileInfo; - -}).call(this); - -Flash = (function() { - var Flash; - - Flash = { - init: function() { - if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { - return $.ready(Flash.initReady); - } - }, - initReady: function() { - if ($.hasStorage) { - return $.global(function() { - if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { - return window.SWFEmbed.init(); - } - }); - } else { - if (g.VIEW === 'thread') { - $.global(function() { - return window.Main.tid = location.pathname.split(/\/+/)[3]; - }); - } - return $.global(function() { - return window.SWFEmbed.init(); - }); - } - } - }; - - return Flash; - -}).call(this); - -Fourchan = (function() { - var Fourchan; - - Fourchan = { - init: function() { - var ref; - if (!(g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive'))) { - return; - } - BoardConfig.ready(this.initBoard); - return Main.ready(this.initReady); - }, - initBoard: function() { - if (g.BOARD.config.code_tags) { - $.on(window, 'prettyprint:cb', function(e) { - var post, pre; - if (!(post = g.posts.get(e.detail.ID))) { - return; - } - if (!(pre = $$('.prettyprint', post.nodes.comment)[+e.detail.i])) { - return; - } - if (!$.hasClass(pre, 'prettyprinted')) { - pre.innerHTML = e.detail.html; - return $.addClass(pre, 'prettyprinted'); - } - }); - $.global(function() { - return window.addEventListener('prettyprint', function(e) { - return window.dispatchEvent(new CustomEvent('prettyprint:cb', { - detail: { - ID: e.detail.ID, - i: e.detail.i, - html: window.prettyPrintOne(e.detail.html) - } - })); - }, false); - }); - Callbacks.Post.push({ - name: 'Parse [code] tags', - cb: Fourchan.code - }); - g.posts.forEach(function(post) { - if (post.callbacksExecuted) { - return Callbacks.Post.execute(post, ['Parse [code] tags'], true); - } - }); - ExpandComment.callbacks.push(Fourchan.code); - } - if (g.BOARD.config.math_tags) { - $.global(function() { - return window.addEventListener('mathjax', function(e) { - if (window.MathJax) { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - } else { - if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { - window.loadMathJax(); - window.loadMathJax = function() {}; - } - if (!e.target.classList.contains('postMessage')) { - return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - }, false); - } - } - }, false); - }); - Callbacks.Post.push({ - name: 'Parse [math] tags', - cb: Fourchan.math - }); - g.posts.forEach(function(post) { - if (post.callbacksExecuted) { - return Callbacks.Post.execute(post, ['Parse [math] tags'], true); - } - }); - return ExpandComment.callbacks.push(Fourchan.math); - } - }, - initReady: function() { - return $.global(function() { - var j, len, node, ref; - window.clickable_ids = false; - ref = document.querySelectorAll('.posteruid, .capcode'); - for (j = 0, len = ref.length; j < len; j++) { - node = ref[j]; - node.removeEventListener('click', window.idClick, false); - } - }); - }, - code: function() { - if (this.isClone) { - return; - } - return $.ready((function(_this) { - return function() { - var i, j, len, pre, ref; - ref = $$('.prettyprint', _this.nodes.comment); - for (i = j = 0, len = ref.length; j < len; i = ++j) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: _this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } - }; - })(this)); - }, - math: function() { - var cb, j, len, wbr, wbrs; - if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { - return; - } - if ((wbrs = $$('wbr', this.nodes.comment)).length) { - for (j = 0, len = wbrs.length; j < len; j++) { - wbr = wbrs[j]; - $.rm(wbr); - } - this.nodes.comment.normalize(); - } - cb = (function(_this) { - return function() { - if (!doc.contains(_this.nodes.comment)) { - return; - } - $.off(d, 'PostsInserted', cb); - return $.event('mathjax', null, _this.nodes.comment); - }; - })(this); - $.on(d, 'PostsInserted', cb); - return cb(); - } - }; - - return Fourchan; - -}).call(this); - -IDColor = (function() { - var IDColor; - - IDColor = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Color User IDs'])) { - return; - } - this.ids = $.dict(); - this.ids['Heaven'] = [0, 0, 0, '#fff']; - return Callbacks.Post.push({ - name: 'Color User IDs', - cb: this.node - }); - }, - node: function() { - var rgb, span, style, uid; - if (this.isClone || !((uid = this.info.uniqueID) && (span = this.nodes.uniqueID))) { - return; - } - rgb = IDColor.ids[uid] || IDColor.compute(uid); - style = span.style; - style.color = rgb[3]; - style.backgroundColor = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")"; - return $.addClass(span, 'painted'); - }, - compute: function(uid) { - var hash, rgb; - hash = g.SITE.uidColor ? g.SITE.uidColor(uid) : parseInt(uid, 16); - rgb = [(hash >> 16) & 0xFF, (hash >> 8) & 0xFF, hash & 0xFF]; - rgb.push($.luma(rgb) > 125 ? '#000' : '#fff'); - return this.ids[uid] = rgb; - } - }; - - return IDColor; - -}).call(this); - -IDHighlight = (function() { - var IDHighlight; - - IDHighlight = { - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - return Callbacks.Post.push({ - name: 'Highlight by User ID', - cb: this.node - }); - }, - uniqueID: null, - node: function() { - if (this.nodes.uniqueIDRoot) { - $.on(this.nodes.uniqueIDRoot, 'click', IDHighlight.click(this)); - } - if (this.nodes.capcode) { - $.on(this.nodes.capcode, 'click', IDHighlight.click(this)); - } - if (!this.isClone) { - return IDHighlight.set(this); - } - }, - set: function(post) { - var match; - match = (post.info.uniqueID || post.info.capcode) === IDHighlight.uniqueID; - return $[match ? 'addClass' : 'rmClass'](post.nodes.post, 'highlight'); - }, - click: function(post) { - return function() { - var uniqueID; - uniqueID = post.info.uniqueID || post.info.capcode; - IDHighlight.uniqueID = IDHighlight.uniqueID === uniqueID ? null : uniqueID; - return g.posts.forEach(IDHighlight.set); - }; - } - }; - - return IDHighlight; - -}).call(this); - -IDPostCount = (function() { - var IDPostCount; - - IDPostCount = { - init: function() { - if (!(g.VIEW === 'thread' && Conf['Count Posts by ID'])) { - return; - } - Callbacks.Thread.push({ - name: 'Count Posts by ID', - cb: function() { - return IDPostCount.thread = this; - } - }); - return Callbacks.Post.push({ - name: 'Count Posts by ID', - cb: this.node - }); - }, - node: function() { - if (this.nodes.uniqueID && this.thread === IDPostCount.thread) { - return $.on(this.nodes.uniqueID, 'mouseover', IDPostCount.count); - } - }, - count: function() { - var n, uniqueID; - uniqueID = Get.postFromNode(this).info.uniqueID; - n = 0; - IDPostCount.thread.posts.forEach(function(post) { - if (post.info.uniqueID === uniqueID) { - return n++; - } - }); - return this.title = n + " post" + (n === 1 ? '' : 's') + " by this ID"; - } - }; - - return IDPostCount; - -}).call(this); - -Keybinds = (function() { - var Keybinds; - - Keybinds = { - init: function() { - var hotkey, init; - if (!Conf['Keybinds']) { - return; - } - for (hotkey in Config.hotkeys) { - $.sync(hotkey, Keybinds.sync); - } - init = function() { - var i, len, node, ref; - $.off(d, '4chanXInitFinished', init); - $.on(d, 'keydown', Keybinds.keydown); - ref = $$('[accesskey]'); - for (i = 0, len = ref.length; i < len; i++) { - node = ref[i]; - node.removeAttribute('accesskey'); - } - }; - return $.on(d, '4chanXInitFinished', init); - }, - sync: function(key, hotkey) { - return Conf[hotkey] = key; - }, - keydown: function(e) { - var base, base1, catalog, i, key, len, notification, notifications, post, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, searchInput, target, thread, threadRoot; - if (!(key = Keybinds.keyCode(e))) { - return; - } - target = e.target; - if ((ref = target.nodeName) === 'INPUT' || ref === 'TEXTAREA') { - if (!(/(Esc|Alt|Ctrl|Meta|Shift\+\w{2,})/.test(key) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { - return; - } - } - if ((ref1 = g.VIEW) === 'index' || ref1 === 'thread') { - threadRoot = Nav.getThread(); - thread = Get.threadFromRoot(threadRoot); - } - switch (key) { - case Conf['Toggle board list']: - if (!Conf['Custom Board Navigation']) { - return; - } - Header.toggleBoardList(); - break; - case Conf['Toggle header']: - Header.toggleBarVisibility(); - break; - case Conf['Open empty QR']: - if (!QR.postingIsEnabled) { - return; - } - Keybinds.qr(); - break; - case Conf['Open QR']: - if (!(QR.postingIsEnabled && threadRoot)) { - return; - } - Keybinds.qr(threadRoot); - break; - case Conf['Open settings']: - Settings.open(); - break; - case Conf['Close']: - if (Settings.dialog) { - Settings.close(); - } else if ((notifications = $$('.notification')).length) { - for (i = 0, len = notifications.length; i < len; i++) { - notification = notifications[i]; - $('.close', notification).click(); - } - } else if (QR.nodes && !(QR.nodes.el.hidden || window.getComputedStyle(QR.nodes.form).display === 'none')) { - if (Conf['Persistent QR']) { - QR.hide(); - } else { - QR.close(); - } - } else if (Embedding.lastEmbed) { - Embedding.closeFloat(); - } else { - return; - } - break; - case Conf['Spoiler tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('spoiler', target); - break; - case Conf['Code tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('code', target); - break; - case Conf['Eqn tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('eqn', target); - break; - case Conf['Math tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('math', target); - break; - case Conf['SJIS tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('sjis', target); - break; - case Conf['Toggle sage']: - if (!(QR.nodes && !QR.nodes.el.hidden)) { - return; - } - Keybinds.sage(); - break; - case Conf['Toggle Cooldown']: - if (!(QR.nodes && !QR.nodes.el.hidden && $.hasClass(QR.nodes.fileSubmit, 'custom-cooldown'))) { - return; - } - QR.toggleCustomCooldown(); - break; - case Conf['Post from URL']: - if (!QR.postingIsEnabled) { - return; - } - QR.handleUrl(''); - break; - case Conf['Add new post']: - if (!QR.postingIsEnabled) { - return; - } - QR.addPost(); - break; - case Conf['Submit QR']: - if (!(QR.nodes && !QR.nodes.el.hidden)) { - return; - } - if (!QR.status()) { - QR.submit(); - } - break; - case Conf['Update']: - switch (g.VIEW) { - case 'thread': - if (!ThreadUpdater.enabled) { - return; - } - ThreadUpdater.update(); - break; - case 'index': - if (!Index.enabled) { - return; - } - Index.update(); - break; - default: - return; - } - break; - case Conf['Watch']: - if (!(ThreadWatcher.enabled && thread)) { - return; - } - ThreadWatcher.toggle(thread); - break; - case Conf['Update thread watcher']: - if (!ThreadWatcher.enabled) { - return; - } - ThreadWatcher.buttonFetchAll(); - break; - case Conf['Toggle thread watcher']: - if (!ThreadWatcher.enabled) { - return; - } - ThreadWatcher.toggleWatcher(); - break; - case Conf['Toggle threading']: - if (!QuoteThreading.ready) { - return; - } - QuoteThreading.toggleThreading(); - break; - case Conf['Mark thread read']: - if (!(g.VIEW === 'index' && thread && UnreadIndex.enabled)) { - return; - } - UnreadIndex.markRead.call(threadRoot); - break; - case Conf['Expand image']: - if (!(ImageExpand.enabled && threadRoot)) { - return; - } - post = Get.postFromNode(Keybinds.post(threadRoot)); - if (post.file) { - ImageExpand.toggle(post); - } - break; - case Conf['Expand images']: - if (!ImageExpand.enabled) { - return; - } - ImageExpand.cb.toggleAll(); - break; - case Conf['Open Gallery']: - if (!Gallery.enabled) { - return; - } - Gallery.cb.toggle(); - break; - case Conf['fappeTyme']: - if (!((ref2 = FappeTyme.nodes) != null ? ref2.fappe : void 0)) { - return; - } - FappeTyme.toggle('fappe'); - break; - case Conf['werkTyme']: - if (!((ref3 = FappeTyme.nodes) != null ? ref3.werk : void 0)) { - return; - } - FappeTyme.toggle('werk'); - break; - case Conf['Front page']: - if (Index.enabled) { - Index.userPageNav(1); - } else { - location.href = "/" + g.BOARD + "/"; - } - break; - case Conf['Open front page']: - $.open(location.origin + "/" + g.BOARD + "/"); - break; - case Conf['Next page']: - if (!(g.VIEW === 'index' && !(typeof (base = g.SITE).isOnePage === "function" ? base.isOnePage(g.BOARD) : void 0))) { - return; - } - if (Index.enabled) { - if ((ref4 = Conf['Index Mode']) !== 'paged' && ref4 !== 'infinite') { - return; - } - $('.next button', Index.pagelist).click(); - } else { - if ((ref5 = $(g.SITE.selectors.nav.next)) != null) { - ref5.click(); - } - } - break; - case Conf['Previous page']: - if (!(g.VIEW === 'index' && !(typeof (base1 = g.SITE).isOnePage === "function" ? base1.isOnePage(g.BOARD) : void 0))) { - return; - } - if (Index.enabled) { - if ((ref6 = Conf['Index Mode']) !== 'paged' && ref6 !== 'infinite') { - return; - } - $('.prev button', Index.pagelist).click(); - } else { - if ((ref7 = $(g.SITE.selectors.nav.prev)) != null) { - ref7.click(); - } - } - break; - case Conf['Search form']: - if (g.VIEW !== 'index') { - return; - } - searchInput = Index.enabled ? Index.searchInput : g.SITE.selectors.searchBox ? $(g.SITE.selectors.searchBox) : void 0; - if (!searchInput) { - return; - } - Header.scrollToIfNeeded(searchInput); - searchInput.focus(); - break; - case Conf['Paged mode']: - if (!Index.enabledOn(g.BOARD)) { - return; - } - location.href = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; - break; - case Conf['Infinite scrolling mode']: - if (!Index.enabledOn(g.BOARD)) { - return; - } - location.href = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; - break; - case Conf['All pages mode']: - if (!Index.enabledOn(g.BOARD)) { - return; - } - location.href = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; - break; - case Conf['Open catalog']: - if (!(catalog = CatalogLinks.catalog())) { - return; - } - location.href = catalog; - break; - case Conf['Cycle sort type']: - if (!Index.enabled) { - return; - } - Index.cycleSortType(); - break; - case Conf['Next thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Nav.scroll(+1); - break; - case Conf['Previous thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Nav.scroll(-1); - break; - case Conf['Expand thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - ExpandThread.toggle(thread); - Header.scrollTo(threadRoot); - break; - case Conf['Open thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Keybinds.open(thread); - break; - case Conf['Open thread tab']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Keybinds.open(thread, true); - break; - case Conf['Next reply']: - if (!threadRoot) { - return; - } - Keybinds.hl(+1, threadRoot); - break; - case Conf['Previous reply']: - if (!threadRoot) { - return; - } - Keybinds.hl(-1, threadRoot); - break; - case Conf['Deselect reply']: - if (!threadRoot) { - return; - } - Keybinds.hl(0, threadRoot); - break; - case Conf['Hide']: - if (!(thread && ThreadHiding.db)) { - return; - } - Header.scrollTo(threadRoot); - ThreadHiding.toggle(thread); - break; - case Conf['Quick Filter MD5']: - if (!threadRoot) { - return; - } - post = Keybinds.post(threadRoot); - Keybinds.hl(+1, threadRoot); - Filter.quickFilterMD5.call(post, e); - break; - case Conf['Previous Post Quoting You']: - if (!(threadRoot && QuoteYou.db)) { - return; - } - QuoteYou.cb.seek('preceding'); - break; - case Conf['Next Post Quoting You']: - if (!(threadRoot && QuoteYou.db)) { - return; - } - QuoteYou.cb.seek('following'); - break; - default: - return; - } - e.preventDefault(); - return e.stopPropagation(); - }, - keyCode: function(e) { - var kc, key; - key = (function() { - switch (kc = e.keyCode) { - case 8: - return ''; - case 13: - return 'Enter'; - case 27: - return 'Esc'; - case 32: - return 'Space'; - case 37: - return 'Left'; - case 38: - return 'Up'; - case 39: - return 'Right'; - case 40: - return 'Down'; - case 188: - return 'Comma'; - case 190: - return 'Period'; - case 191: - return 'Slash'; - case 59: - case 186: - return 'Semicolon'; - default: - if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { - return String.fromCharCode(kc).toLowerCase(); - } else if ((96 <= kc && kc <= 105)) { - return String.fromCharCode(kc - 48).toLowerCase(); - } else { - return null; - } - } - })(); - if (key) { - if (e.altKey) { - key = 'Alt+' + key; - } - if (e.ctrlKey) { - key = 'Ctrl+' + key; - } - if (e.metaKey) { - key = 'Meta+' + key; - } - if (e.shiftKey) { - key = 'Shift+' + key; - } - } - return key; - }, - post: function(thread) { - var s; - s = g.SITE.selectors; - return $("" + s.postContainer + s.highlightable.reply + "." + g.SITE.classes.highlight, thread) || $("" + (g.SITE.isOPContainerThread ? s.thread : s.postContainer) + s.highlightable.op, thread); - }, - qr: function(thread) { - QR.open(); - if (thread != null) { - QR.quote.call(Keybinds.post(thread)); - } - return QR.nodes.com.focus(); - }, - tags: function(tag, ta) { - var range, selEnd, selStart, value; - BoardConfig.ready(function() { - var config, supported; - config = g.BOARD.config; - supported = (function() { - switch (tag) { - case 'spoiler': - return !!config.spoilers; - case 'code': - return !!config.code_tags; - case 'math': - case 'eqn': - return !!config.math_tags; - case 'sjis': - return !!config.sjis_tags; - } - })(); - if (!supported) { - return new Notice('warning', "[" + tag + "] tags are not supported on /" + g.BOARD + "/.", 20); - } - }); - 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('input', null, ta); - }, - sage: function() { - var isSage; - isSage = /sage/i.test(QR.nodes.email.value); - return QR.nodes.email.value = isSage ? "" : "sage"; - }, - open: function(thread, tab) { - var url; - if (g.VIEW !== 'index') { - return; - } - url = Get.url('thread', thread); - if (tab) { - return $.open(url); - } else { - return location.href = url; - } - }, - hl: function(delta, thread) { - var axis, height, highlight, i, len, next, postEl, replies, reply, replySelector, root; - replySelector = "" + g.SITE.selectors.postContainer + g.SITE.selectors.highlightable.reply; - highlight = g.SITE.classes.highlight; - postEl = $(replySelector + "." + highlight, thread); - if (!delta) { - if (postEl) { - $.rmClass(postEl, highlight); - } - return; - } - if (postEl) { - height = postEl.getBoundingClientRect().height; - if (Header.getTopOf(postEl) >= -height && Header.getBottomOf(postEl) >= -height) { - root = Get.postFromNode(postEl).nodes.root; - axis = delta === +1 ? 'following' : 'preceding'; - if (!(next = $.x(axis + "-sibling::" + g.SITE.xpath.replyContainer + "[not(@hidden) and not(child::div[@class='stub'])][1]", root))) { - return; - } - if (!next.matches(replySelector)) { - next = $(replySelector, next); - } - Header.scrollToIfNeeded(next, delta === +1); - $.addClass(next, highlight); - $.rmClass(postEl, highlight); - return; - } - $.rmClass(postEl, highlight); - } - replies = $$(replySelector, thread); - if (delta === -1) { - replies.reverse(); - } - for (i = 0, len = replies.length; i < len; i++) { - reply = replies[i]; - if (delta === +1 && Header.getTopOf(reply) > 0 || delta === -1 && Header.getBottomOf(reply) > 0) { - $.addClass(reply, highlight); - return; - } - } - } - }; - - return Keybinds; - -}).call(this); - -ModContact = (function() { - var ModContact; - - ModContact = { - init: function() { - var ref; - if (!(g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - return Callbacks.Post.push({ - name: 'Mod Contact Links', - cb: this.node - }); - }, - node: function() { - var links, moveNote, moved; - if (this.isClone || !$.hasOwn(ModContact.specific, this.info.capcode)) { - return; - } - links = $.el('span', { - className: 'contact-links brackets-wrap' - }); - $.extend(links, ModContact.template(this.info.capcode)); - $.after(this.nodes.capcode, links); - if ((moved = this.info.comment.match(/This thread was moved to >>>\/(\w+)\//)) && $.hasOwn(ModContact.moveNote, moved[1])) { - moveNote = $.el('div', { - className: 'move-note' - }); - $.extend(moveNote, ModContact.moveNote[moved[1]]); - return $.add(this.nodes.post, moveNote); - } - }, - template: function(capcode) { - return {innerHTML: "feedback" + (ModContact.specific[capcode]()).innerHTML}; - }, - specific: { - Mod: function() { - return {innerHTML: " IRC"}; - }, - Manager: function() { - return ModContact.specific.Mod(); - }, - Developer: function() { - return {innerHTML: " github"}; - }, - Admin: function() { - return {innerHTML: " twitter"}; - } - }, - moveNote: { - qa: {innerHTML: "Moving a thread to /qa/ does not imply mods will read it. If you wish to contact mods, use feedback (https://www.4chan.org/feedback) or IRC (https://www.4chan-x.net/4chan-irc.html)."} - } - }; - - return ModContact; - -}).call(this); - -Nav = (function() { - var Nav; - - Nav = { - init: function() { - var append, next, prev, span; - switch (g.VIEW) { - case 'index': - if (!Conf['Index Navigation']) { - return; - } - break; - case 'thread': - if (!Conf['Reply Navigation']) { - return; - } - break; - default: - return; - } - span = $.el('span', { - id: 'navlinks' - }); - prev = $.el('a', { - textContent: '▲', - href: 'javascript:;' - }); - next = $.el('a', { - textContent: '▼', - href: 'javascript:;' - }); - $.on(prev, 'click', this.prev); - $.on(next, 'click', this.next); - $.add(span, [prev, $.tn(' '), next]); - append = function() { - $.off(d, '4chanXInitFinished', append); - return $.add(d.body, span); - }; - return $.on(d, '4chanXInitFinished', append); - }, - prev: function() { - if (g.VIEW === 'thread') { - return window.scrollTo(0, 0); - } else { - return Nav.scroll(-1); - } - }, - next: function() { - if (g.VIEW === 'thread') { - return window.scrollTo(0, d.body.scrollHeight); - } else { - return Nav.scroll(+1); - } - }, - getThread: function() { - var i, len, ref, thread, threadRoot; - if (g.VIEW === 'thread') { - return g.threads.get(g.BOARD + "." + g.THREADID).nodes.root; - } - if ($.hasClass(doc, 'catalog-mode')) { - return; - } - ref = $$(g.SITE.selectors.thread); - for (i = 0, len = ref.length; i < len; i++) { - threadRoot = ref[i]; - thread = Get.threadFromRoot(threadRoot); - if (thread.isHidden && !thread.stub) { - continue; - } - if (Header.getTopOf(threadRoot) >= -threadRoot.getBoundingClientRect().height) { - return threadRoot; - } - } - }, - scroll: function(delta) { - var axis, extra, next, ref, thread, top; - if ((ref = d.activeElement) != null) { - ref.blur(); - } - thread = Nav.getThread(); - if (!thread) { - return; - } - axis = delta === +1 ? 'following' : 'preceding'; - if (next = $.x(axis + "-sibling::" + g.SITE.xpath.thread + "[not(@hidden)][1]", thread)) { - top = Header.getTopOf(thread); - if (delta === +1 && top < 5 || delta === -1 && top > -5) { - thread = next; - } - } - extra = Header.getTopOf(thread) + doc.clientHeight - d.body.getBoundingClientRect().bottom; - if (extra > 0) { - d.body.style.marginBottom = extra + "px"; - } - Header.scrollTo(thread); - if (extra > 0 && !Nav.haveExtra) { - Nav.haveExtra = true; - return $.on(d, 'scroll', Nav.removeExtra); - } - }, - removeExtra: function() { - var extra; - extra = doc.clientHeight - d.body.getBoundingClientRect().bottom; - if (extra > 0) { - return d.body.style.marginBottom = extra + "px"; - } else { - d.body.style.marginBottom = ''; - delete Nav.haveExtra; - return $.off(d, 'scroll', Nav.removeExtra); - } - } - }; - - return Nav; - -}).call(this); - -NormalizeURL = (function() { - var NormalizeURL; - - NormalizeURL = { - init: function() { - var pathname; - if (!Conf['Normalize URL']) { - return; - } - pathname = location.pathname.split(/\/+/); - if (g.SITE.software === 'yotsuba') { - switch (g.VIEW) { - case 'thread': - pathname[2] = 'thread'; - pathname = pathname.slice(0, 4); - break; - case 'index': - pathname = pathname.slice(0, 3); - } - } - pathname = pathname.join('/'); - if (location.pathname !== pathname) { - return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); - } - } - }; - - return NormalizeURL; - -}).call(this); - -PSA = (function() { - var PSA, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - PSA = { - init: function() { - var announcement, el; - if (g.SITE.software === 'yotsuba' && g.BOARD.ID === 'qa') { - announcement = { - innerHTML: "Stay in touch with your /qa/ friends!" - }; - el = $.el('div', { - className: 'fcx-announcement' - }, announcement); - $.onExists(doc, '.boardBanner', function(banner) { - return $.after(banner, el); - }); - } - if ('samachan.org' in Conf['siteProperties'] && indexOf.call(Conf['PSAseen'], 'samachan') < 0) { - el = $.el('span', { - innerHTML: "Looking for a new home?
    Some former Samachan users are regrouping on SushiChan.

    (a message from 4chan X)" - }); - return Main.ready(function() { - new Notice('info', el); - Conf['PSAseen'].push('samachan'); - return $.set('PSAseen', Conf['PSAseen']); - }); - } - } - }; - - return PSA; - -}).call(this); - -PSAHiding = (function() { - var PSAHiding, - slice = [].slice; - - PSAHiding = { - init: function() { - if (!(Conf['Announcement Hiding'] && g.SITE.selectors.psa)) { - return; - } - $.addClass(doc, 'hide-announcement'); - $.onExists(doc, g.SITE.selectors.psa, this.setup); - return $.ready(function() { - if (!$(g.SITE.selectors.psa)) { - return $.rmClass(doc, 'hide-announcement'); - } - }); - }, - setup: function(psa) { - var btn, entry, hr, ref, ref1, ref2; - PSAHiding.psa = psa; - PSAHiding.text = (ref = psa.dataset.utc) != null ? ref : psa.innerHTML; - if (g.SITE.selectors.psaTop && (hr = (ref1 = $(g.SITE.selectors.psaTop)) != null ? ref1.previousElementSibling : void 0) && hr.nodeName === 'HR') { - PSAHiding.hr = hr; - } - PSAHiding.content = $.el('div'); - entry = { - el: $.el('a', { - textContent: 'Show announcement', - className: 'show-announcement', - href: 'javascript:;' - }), - order: 50, - open: function() { - return psa.hidden; - } - }; - Header.menu.addEntry(entry); - $.on(entry.el, 'click', PSAHiding.toggle); - PSAHiding.btn = btn = $.el('a', { - title: 'Mark announcement as read and hide.', - className: 'hide-announcement-button fa fa-minus-square', - href: 'javascript:;' - }); - $.on(btn, 'click', PSAHiding.toggle); - if (((ref2 = psa.firstChild) != null ? ref2.tagName : void 0) === 'HR') { - $.after(psa.firstChild, btn); - } else { - $.prepend(psa, btn); - } - PSAHiding.sync(Conf['hiddenPSAList']); - $.rmClass(doc, 'hide-announcement'); - return $.sync('hiddenPSAList', PSAHiding.sync); - }, - toggle: function() { - var hide, set; - hide = $.hasClass(this, 'hide-announcement-button'); - set = function(hiddenPSAList) { - if (hide) { - return hiddenPSAList[g.SITE.ID] = PSAHiding.text; - } else { - return delete hiddenPSAList[g.SITE.ID]; - } - }; - set(Conf['hiddenPSAList']); - PSAHiding.sync(Conf['hiddenPSAList']); - return $.get('hiddenPSAList', Conf['hiddenPSAList'], function(arg) { - var hiddenPSAList; - hiddenPSAList = arg.hiddenPSAList; - set(hiddenPSAList); - return $.set('hiddenPSAList', hiddenPSAList); - }); - }, - sync: function(hiddenPSAList) { - var content, psa, ref; - psa = PSAHiding.psa, content = PSAHiding.content; - psa.hidden = hiddenPSAList[g.SITE.ID] === PSAHiding.text; - if (psa.hidden) { - $.add(content, slice.call(psa.childNodes)); - } else { - $.add(psa, slice.call(content.childNodes)); - } - return (ref = PSAHiding.hr) != null ? ref.hidden = psa.hidden : void 0; - } - }; - - return PSAHiding; - -}).call(this); - -PassMessage = (function() { - var PassMessage; - - PassMessage = { - init: function() { - var close, msg; - if (Conf['passMessageClosed']) { - return; - } - msg = $.el('div', { - className: 'box-outer top-box' - }, {innerHTML: "

    Trouble buying a 4chan Pass? (a message from 4chan X) ×

    Check the 4chan X wiki for alternative solutions.
    "}); - msg.style.cssText = 'padding-bottom: 0;'; - close = $('a', msg); - $.on(close, 'click', function() { - $.rm(msg); - return $.set('passMessageClosed', true); - }); - return $.ready(function() { - var hd; - if ((hd = $.id('hd'))) { - return $.after(hd, msg); - } else { - return $.prepend(d.body, msg); - } - }); - } - }; - - return PassMessage; - -}).call(this); - -PostJumper = (function() { - var PostJumper; - - PostJumper = { - init: function() { - var ref; - if (!(Conf['Unique ID and Capcode Navigation'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.buttons = this.makeButtons(); - return Callbacks.Post.push({ - name: 'Post Jumper', - cb: this.node - }); - }, - node: function() { - var buttons, i, len, ref; - if (this.isClone) { - ref = $$('.postJumper', this.nodes.info); - for (i = 0, len = ref.length; i < len; i++) { - buttons = ref[i]; - PostJumper.addListeners(buttons); - } - return; - } - if (this.nodes.uniqueIDRoot) { - PostJumper.addButtons(this, 'uniqueID'); - } - if (this.nodes.capcode) { - return PostJumper.addButtons(this, 'capcode'); - } - }, - addButtons: function(post, type) { - var buttons, value; - value = post.info[type]; - buttons = PostJumper.buttons.cloneNode(true); - $.extend(buttons.dataset, { - type: type, - value: value - }); - $.after(post.nodes[type + (type === 'capcode' ? '' : 'Root')], buttons); - return PostJumper.addListeners(buttons); - }, - addListeners: function(buttons) { - $.on(buttons.firstChild, 'click', PostJumper.buttonClick); - return $.on(buttons.lastChild, 'click', PostJumper.buttonClick); - }, - buttonClick: function() { - var dir, toJumper; - dir = $.hasClass(this, 'prev') ? -1 : 1; - if ((toJumper = PostJumper.find(this.parentNode, dir))) { - return PostJumper.scroll(this.parentNode, toJumper); - } - }, - find: function(jumper, dir) { - var axis, jumper2, ref, type, value, xpath; - ref = jumper.dataset, type = ref.type, value = ref.value; - xpath = "span[contains(@class,\"postJumper\") and @data-value=\"" + value + "\" and @data-type=\"" + type + "\"]"; - axis = dir < 0 ? 'preceding' : 'following'; - jumper2 = jumper; - while ((jumper2 = $.x(axis + "::" + xpath, jumper2))) { - if (jumper2.getBoundingClientRect().height) { - return jumper2; - } - } - if ((jumper2 = $.x("(//" + xpath + ")[" + (dir < 0 ? 'last()' : '1') + "]"))) { - if (jumper2.getBoundingClientRect().height) { - return jumper2; - } - } - while ((jumper2 = $.x(axis + "::" + xpath, jumper2)) && jumper2 !== jumper) { - if (jumper2.getBoundingClientRect().height) { - return jumper2; - } - } - return null; - }, - makeButtons: function() { - var charNext, charPrev, classNext, classPrev, span; - charPrev = '\u23EB'; - charNext = '\u23EC'; - classPrev = 'prev'; - classNext = 'next'; - span = $.el('span', { - className: 'postJumper' - }); - $.extend(span, {innerHTML: "" + E(charPrev) + "" + E(charNext) + ""}); - return span; - }, - scroll: function(fromJumper, toJumper) { - var destPos, prevPos; - prevPos = fromJumper.getBoundingClientRect().top; - destPos = toJumper.getBoundingClientRect().top; - return window.scrollBy(0, destPos - prevPos); - } - }; - - return PostJumper; - -}).call(this); - -RelativeDates = (function() { - var RelativeDates, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - RelativeDates = { - INTERVAL: $.MINUTE / 2, - init: function() { - var ref; - if (((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Relative Post Dates'] && !Conf['Relative Date Title'] || Index.enabled) { - this.flush(); - $.on(d, 'visibilitychange PostsInserted', this.flush); - } - if (Conf['Relative Post Dates']) { - return Callbacks.Post.push({ - name: 'Relative Post Dates', - cb: this.node - }); - } - }, - node: function() { - var dateEl; - if (!this.info.date) { - return; - } - dateEl = this.nodes.date; - if (Conf['Relative Date Title']) { - $.on(dateEl, 'mouseover', (function(_this) { - return function() { - return RelativeDates.hover(_this); - }; - })(this)); - return; - } - if (this.isClone) { - return; - } - dateEl.title = dateEl.textContent; - return RelativeDates.update(this); - }, - relative: function(diff, now, date, abbrev) { - var days, months, number, rounded, unit, years; - unit = (number = diff / $.DAY) >= 1 ? (years = now.getFullYear() - date.getFullYear(), months = now.getMonth() - date.getMonth(), days = now.getDate() - date.getDate(), years > 1 ? (number = years - (months < 0 || months === 0 && days < 0), 'year') : years === 1 && (months > 0 || months === 0 && days >= 0) ? (number = years, 'year') : (months = months + 12 * years) > 1 ? (number = months - (days < 0), 'month') : months === 1 && days >= 0 ? (number = months, 'month') : 'day') : (number = diff / $.HOUR) >= 1 ? 'hour' : (number = diff / $.MINUTE) >= 1 ? 'minute' : (number = Math.max(0, diff) / $.SECOND, 'second'); - rounded = Math.round(number); - if (abbrev) { - unit = unit === 'month' ? 'mo' : unit[0]; - } else { - if (rounded !== 1) { - unit += 's'; - } - } - if (abbrev) { - return "" + rounded + unit; - } else { - return rounded + " " + unit + " ago"; - } - }, - stale: [], - flush: function() { - var data, i, len, now, ref; - if (d.hidden) { - return; - } - now = new Date(); - ref = RelativeDates.stale; - for (i = 0, len = ref.length; i < len; i++) { - data = ref[i]; - RelativeDates.update(data, now); - } - RelativeDates.stale = []; - clearTimeout(RelativeDates.timeout); - return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL); - }, - hover: function(post) { - var date, diff, now; - date = post.info.date; - now = new Date(); - diff = now - date; - return post.nodes.date.title = RelativeDates.relative(diff, now, date); - }, - update: function(data, now) { - var abbrev, date, diff, i, isPost, len, ref, relative, singlePost; - isPost = data instanceof Post; - if (isPost) { - date = data.info.date; - abbrev = false; - } else { - date = new Date(+data.dataset.utc); - abbrev = !!data.dataset.abbrev; - } - now || (now = new Date()); - diff = now - date; - relative = RelativeDates.relative(diff, now, date, abbrev); - if (isPost) { - ref = [data].concat(data.clones); - for (i = 0, len = ref.length; i < len; i++) { - singlePost = ref[i]; - singlePost.nodes.date.firstChild.textContent = relative; - } - } else { - data.firstChild.textContent = relative; - } - return RelativeDates.setOwnTimeout(diff, data); - }, - setOwnTimeout: function(diff, data) { - var delay; - delay = diff < $.MINUTE ? $.SECOND - (diff + $.SECOND / 2) % $.SECOND : diff < $.HOUR ? $.MINUTE - (diff + $.MINUTE / 2) % $.MINUTE : diff < $.DAY ? $.HOUR - (diff + $.HOUR / 2) % $.HOUR : $.DAY - (diff + $.DAY / 2) % $.DAY; - return setTimeout(RelativeDates.markStale, delay, data); - }, - markStale: function(data) { - if (indexOf.call(RelativeDates.stale, data) >= 0) { - return; - } - if (data instanceof Post && !g.posts.get(data.fullID)) { - return; - } - if (data instanceof Element && !doc.contains(data)) { - return; - } - return RelativeDates.stale.push(data); - } - }; - - return RelativeDates; - -}).call(this); - -RemoveSpoilers = (function() { - var RemoveSpoilers, - slice = [].slice; - - RemoveSpoilers = { - init: function() { - if (Conf['Reveal Spoilers']) { - $.addClass(doc, 'reveal-spoilers'); - } - if (!Conf['Remove Spoilers']) { - return; - } - Callbacks.Post.push({ - name: 'Reveal Spoilers', - cb: this.node - }); - if (g.VIEW === 'archive') { - return $.ready(function() { - return RemoveSpoilers.unspoiler($.id('arc-list')); - }); - } - }, - node: function() { - return RemoveSpoilers.unspoiler(this.nodes.comment); - }, - unspoiler: function(el) { - var i, len, span, spoiler, spoilers; - spoilers = $$(g.SITE.selectors.spoiler, el); - for (i = 0, len = spoilers.length; i < len; i++) { - spoiler = spoilers[i]; - span = $.el('span', { - className: 'removed-spoiler' - }); - $.replace(spoiler, span); - $.add(span, slice.call(spoiler.childNodes)); - } - } - }; - - return RemoveSpoilers; - -}).call(this); - -Report = (function() { - var Report; - - Report = { - init: function() { - var match; - if (!(match = location.search.match(/\bno=(\d+)/))) { - return; - } - Captcha.replace.init(); - this.postID = +match[1]; - return $.ready(this.ready); - }, - ready: function() { - $.addStyle(CSS.report); - if (Conf['Archive Report']) { - Report.archive(); - } - new MutationObserver(function() { - Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return Report.fit('body'); - }).observe(d.body, { - childList: true, - attributes: true, - subtree: true - }); - return Report.fit('body'); - }, - fit: function(selector) { - var dy, el; - if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { - return; - } - dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; - if (dy > 0) { - return window.resizeBy(0, dy); - } - }, - archive: function() { - var enabled, fieldset, form, match, message, reason, submit, types, urls; - if (!(urls = Redirect.report(g.BOARD.ID)).length) { - return; - } - form = $('form'); - types = $.id('reportTypes'); - message = $('h3'); - fieldset = $.el('fieldset', { - id: 'archive-report', - hidden: true - }, {innerHTML: ""}); - enabled = $('#archive-report-enabled', fieldset); - reason = $('#archive-report-reason', fieldset); - submit = $('#archive-report-submit', fieldset); - $.on(enabled, 'change', function() { - return reason.disabled = !this.checked; - }); - if (form && types) { - fieldset.hidden = !$('[value="31"]', types).checked; - $.on(types, 'change', function(e) { - fieldset.hidden = e.target.value !== '31'; - return Report.fit('body'); - }); - $.after(types, fieldset); - Report.fit('body'); - $.one(form, 'submit', function(e) { - if (!fieldset.hidden && enabled.checked) { - e.preventDefault(); - return Report.archiveSubmit(urls, reason.value, (function(_this) { - return function(results) { - _this.action = '#archiveresults=' + encodeURIComponent(JSON.stringify(results)); - return _this.submit(); - }; - })(this)); - } - }); - } else if (message) { - fieldset.hidden = /Report submitted!/.test(message.textContent); - $.on(enabled, 'change', function() { - return submit.hidden = !this.checked; - }); - $.after(message, fieldset); - $.on(submit, 'click', function() { - return Report.archiveSubmit(urls, reason.value, Report.archiveResults); - }); - } - if ((match = location.hash.match(/^#archiveresults=(.*)$/))) { - try { - return Report.archiveResults(JSON.parse(decodeURIComponent(match[1]))); - } catch (error) {} - } - }, - archiveSubmit: function(urls, reason, cb) { - var fn, form, i, len, name, ref, results, url; - form = $.formData({ - board: g.BOARD.ID, - num: Report.postID, - reason: reason - }); - results = []; - fn = function(name, url) { - return $.ajax(url, { - onloadend: function() { - results.push([ - name, this.response || { - error: '' - } - ]); - if (results.length === urls.length) { - return cb(results); - } - }, - form: form - }); - }; - for (i = 0, len = urls.length; i < len; i++) { - ref = urls[i], name = ref[0], url = ref[1]; - fn(name, url); - } - }, - archiveResults: function(results) { - var fieldset, i, len, line, name, ref, response; - fieldset = $.id('archive-report'); - for (i = 0, len = results.length; i < len; i++) { - ref = results[i], name = ref[0], response = ref[1]; - line = $.el('h3', { - className: 'archive-report-response' - }); - if ('success' in response) { - $.addClass(line, 'archive-report-success'); - line.textContent = name + ": " + response.success; - } else { - $.addClass(line, 'archive-report-error'); - line.textContent = name + ": " + (response.error || 'Error reporting post.'); - } - if (fieldset) { - $.before(fieldset, line); - } else { - $.add(d.body, line); - } - } - } - }; - - return Report; - -}).call(this); - -ThreadLinks = (function() { - var ThreadLinks; - - ThreadLinks = { - init: function() { - if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { - return; - } - Callbacks.Post.push({ - name: 'Thread Links', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Thread Links', - cb: this.catalogNode - }); - }, - node: function() { - if (this.isReply || this.isClone) { - return; - } - return ThreadLinks.process(this.nodes.reply); - }, - catalogNode: function() { - return ThreadLinks.process(this.nodes.thumb.parentNode); - }, - process: function(link) { - return link.target = '_blank'; - } - }; - - return ThreadLinks; - -}).call(this); - -Time = (function() { - var Time; - - Time = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Time Formatting'])) { - return; - } - return Callbacks.Post.push({ - name: 'Time Formatting', - cb: this.node - }); - }, - node: function() { - var textContent; - if (!this.info.date || this.isClone) { - return; - } - textContent = this.nodes.date.textContent; - return this.nodes.date.textContent = textContent.match(/^\s*/)[0] + Time.format(Conf['time'], this.info.date) + textContent.match(/\s*$/)[0]; - }, - format: function(formatString, date) { - return formatString.replace(/%(.)/g, function(s, c) { - if ($.hasOwn(Time.formatters, c)) { - return Time.formatters[c].call(date); - } else { - return s; - } - }); - }, - day: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - localeFormat: function(date, options, defaultValue) { - if (Conf['timeLocale']) { - try { - return Intl.DateTimeFormat(Conf['timeLocale'], options).format(date); - } catch (error) {} - } - return defaultValue; - }, - localeFormatPart: function(date, options, part, defaultValue) { - var parts; - if (Conf['timeLocale']) { - try { - parts = Intl.DateTimeFormat(Conf['timeLocale'], options).formatToParts(date); - return parts.map(function(x) { - if (x.type === part) { - return x.value; - } else { - return ''; - } - }).join(''); - } catch (error) {} - } - return defaultValue; - }, - zeroPad: function(n) { - if (n < 10) { - return "0" + n; - } else { - return n; - } - }, - formatters: { - a: function() { - return Time.localeFormat(this, { - weekday: 'short' - }, Time.day[this.getDay()].slice(0, 3)); - }, - A: function() { - return Time.localeFormat(this, { - weekday: 'long' - }, Time.day[this.getDay()]); - }, - b: function() { - return Time.localeFormat(this, { - month: 'short' - }, Time.month[this.getMonth()].slice(0, 3)); - }, - B: function() { - return Time.localeFormat(this, { - month: 'long' - }, Time.month[this.getMonth()]); - }, - d: function() { - return Time.zeroPad(this.getDate()); - }, - e: function() { - return this.getDate(); - }, - H: function() { - return Time.zeroPad(this.getHours()); - }, - I: function() { - return Time.zeroPad(this.getHours() % 12 || 12); - }, - k: function() { - return this.getHours(); - }, - l: function() { - return this.getHours() % 12 || 12; - }, - m: function() { - return Time.zeroPad(this.getMonth() + 1); - }, - M: function() { - return Time.zeroPad(this.getMinutes()); - }, - p: function() { - return Time.localeFormatPart(this, { - hour: 'numeric', - hour12: true - }, 'dayperiod', (this.getHours() < 12 ? 'AM' : 'PM')); - }, - P: function() { - return Time.formatters.p.call(this).toLowerCase(); - }, - S: function() { - return Time.zeroPad(this.getSeconds()); - }, - y: function() { - return this.getFullYear().toString().slice(2); - }, - Y: function() { - return this.getFullYear(); - }, - '%': function() { - return '%'; - } - } - }; - - return Time; - -}).call(this); - -Tinyboard = (function() { - var Tinyboard; - - Tinyboard = { - init: function() { - if (g.SITE.software !== 'tinyboard') { - return; - } - if (g.VIEW === 'thread') { - return Main.ready(function() { - return $.global(function() { - var base, boardID, form, originalNoko, ref, ref1, ref2, threadID; - ref = document.currentScript.dataset, boardID = ref.boardID, threadID = ref.threadID; - threadID = +threadID; - form = document.querySelector('form[name="post"]'); - window.$(document).ajaxComplete(function(event, request, settings) { - var detail, noko, postID, redirect, ref1, ref2; - if (settings.url !== form.action) { - return; - } - if (!(postID = +((ref1 = request.responseJSON) != null ? ref1.id : void 0))) { - return; - } - detail = { - boardID: boardID, - threadID: threadID, - postID: postID - }; - try { - ref2 = request.responseJSON, redirect = ref2.redirect, noko = ref2.noko; - if (redirect && (typeof originalNoko !== "undefined" && originalNoko !== null) && !originalNoko && !noko) { - detail.redirect = redirect; - } - } catch (error) {} - event = new CustomEvent('QRPostSuccessful', { - bubbles: true, - detail: detail - }); - return document.dispatchEvent(event); - }); - originalNoko = (ref1 = window.tb_settings) != null ? (ref2 = ref1.ajax) != null ? ref2.always_noko_replies : void 0 : void 0; - return ((base = (window.tb_settings || (window.tb_settings = {}))).ajax || (base.ajax = {})).always_noko_replies = true; - }, { - boardID: g.BOARD.ID, - threadID: g.THREADID - }); - }); - } - } - }; - - return Tinyboard; - -}).call(this); - -Favicon = (function() { - var Favicon; - - Favicon = { - init: function() { - return $.asap((function() { - return d.head && (Favicon.el = $('link[rel="shortcut icon"]', d.head)); - }), Favicon.initAsap); - }, - set: function(status) { - Favicon.status = status; - if (Favicon.el) { - Favicon.el.href = Favicon[status]; - return $.add(d.head, Favicon.el); - } - }, - initAsap: function() { - var href; - Favicon.el.type = 'image/x-icon'; - href = Favicon.el.href; - Favicon.isSFW = /ws\.ico$/.test(href); - Favicon["default"] = href; - Favicon["switch"](); - if (Favicon.status) { - return Favicon.set(Favicon.status); - } - }, - "switch": function() { - var f, i, items, t; - items = { - ferongr: ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///9zBQC/AADpDAP/gID/q6voCwJJTwpOAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxUlEQVR42q1TOwrCQBB9s0FRtJI0WoqFtSLYegoP4gVSeJsUHsHSI3iFeIqRXXgwrhlXwYHHhLwPTB7B36abBCV+0pA4DUBQUNZYQptGtW3jtoKyxgoe0yrBCoyZfL/5ioQ3URZOXW9I341l3oo+NXEZiW4CEuIzvPECopED4OaZ3RNmeAm4u+a8Jr5f17VyVoL8fr8qcltzwlyyj2iqcgPOQ9ExkHAITgD75bYBe0A5S4H/P9htuWMF3QXoQpwaKeT+lnsC6JE5I6aq6fEAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///8AcH4AtswA2PJ55fKi6fIA1/FtpPADAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxElEQVQ4y2NgoBq4/vE/HJOsBiRQUIfA2AzBqQYqUfn00/9FLz+BaQxDCKqBmX7jExijKEDSDJPHrnnbGQhGV4RmOFwdVkNwhQMheYwQxhaIi7b9Z9A3gWAQm2BUoQOgRhgA8o7j1ozLC4LCyAZcx6kZI5qg4kLKqggDFFWxJySsUQVzlb4pwgAJaTRvokcVNgOqOv8zcHBCsL07DgNg8YsczzA5MxtUL+DMD8g0slxI/H8GQ/P/DJKyeKIRpglXZsIiBwBhP5O+VbI/JgAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///8oeQBJ3ABV/wHM/7Lu/+ZU/gAqUP3dAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAx0lEQVQ4y2NgoBYI+cfwH4ZJVgMS0KhEYGyG4FQDkzjzf9P/d/+fgWl0QwiqgSkI/c8IxsgKkDXD5LFq9rwDweiK0A2HqcNqCK5wICSPEcLYAtH+AMN/IXMIBrEJRie6OEgjDAC5x3FqxuUFNiEUA67j1IweTTBxBQ1puAG86jgSEraogskJWSBcwCGF5k30qMJmgMFEhv/MXBAs5oLDAFj8IsczTE7UEeECbhU8+QGZRpaTi2b4L2zF8J9TGk80wjThykzY5AAW/2O1C2mIbgAAAABJRU5ErkJggg=='], - 'xat-': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAG1BMVEX+AACLkZFub2yfaF3zZGIAAAD/AAD/iYr/zs8IPcF6AAAABXRSTlMAeprJ7xzg6IEAAABZSURBVAjXY2DABKGBSkqioQwMrGmpxsZhaQEMDGFpIa5pqSCRtPDSNJBIaGh5eShQDYOye0V7iREKAyQFYoiCFAcyILQDGcGmEEZYkGoqiMHKysAQEICwGwAAjBmBqhYlagAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAPFBMVEUAAACEgoBva2ilamDxcG7IaWYgFBNOSEf//f0PDQwBAAA7LCwAAAD/AAD+hIX+m5z+zc5HAADPAAAGAADl032uAAAADHRSTlMAzNv0/vz+6v3+7ALrmfyXAAAAaUlEQVQY042PyxKAIAhFAc1eV7T6/3/N8VXOtAgWwBm4ANEPA8AswpySXHvvYZLlpBNrh9pDtcSqAQ1BUTVIjNUQY5icmwfglmXNgE0d6QBF9GigrU0A9LoM53U1kFzk6SBQuWfD/vHqDUCpBmVKTTM4AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIVBMVEUAAACRjop4dXVpZ2tdcI9dfKdisfMAAAAumMN9xv+s2/+PADT2AAAAB3RSTlMAepGdv83v3HIc4QAAAFxJREFUCNdjYMAE5YXKRuLlDAzsHe2uIRUdBQwMFR1l6R3tIJGOyukdIJHy8lkry4FqGEwzV62aFozMUAFJOQEZ4iDFhQwI7UBGaTiEUVFs3g5isLMzMBQUIOwGAJRlIu9hk08QAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAMFBMVEUAAACAgYVlc4ljsu4AAAAAAAAAAAAumMODyP6b1P6e1f/g8v89msgSIiwNFxwbPU3tQYj5AAAABnRSTlMAxej+9VTmD9ciAAAAZElEQVQI12NgwARpiUKKYmkMDGzlZUpK6eUJDAzp5clm5WUgkfKMtnKQSFpa54o0oBoGJYvZO88+gjJu7wMyhIBS2SCGGFDxaxADpP32NjAjSe0bSFd6epIaWISNjYEhJRVhNwAGlyJpYtcvcAAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAHlBMVEUfJSCRi5Frbm9dn19082KR/30AAABmzDOq/5vZ/9Gt/vt2AAAABnRSTlMAe5rJ7/4vxEp4AAAAWUlEQVQI12NgwARpiUpKYmkMDGzlZcbG6eUJDAzp5Slu5WUgkfLUsHKQSFpaRGsaUA2DsmvnjBAjFAZICsQQAylOZEBoBzKSzSCM9CS1MhCDjY2BISEBYTcAtgAcKSK2vuIAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAM1BMVEUAAACBj39tfm1qj2RepFlu2VQAAQAAAAAAAABmyzOX/oSr/pus/pzk/98PGgtatC4CBAI1ENblAAAACHRSTlMA09/p9v77ig0SBcQAAABnSURBVBjTjY9LDsAgCEQRsR2xWu9/2hK/adJFYQG8wABEPwyAYzNnSatjjPAiviWLhPCqI1R7HBrQdCmGBrEETTmnUAq/QMm5dODHyAQOXXR1zLUGsIEI7lonMGfeHQTq9xw4P159AIxSBSC53km7AAAAAElFTkSuQmCC'], - Mayhem: ['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'], - '4chanJS': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAD/AABnZ2f///8nFk05AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEUAAAAAAAD/AABmZmYA/wBD99DBAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE9JREFUCNdljcsRACEIQ5MOiNKAdGAJ9N/Uiu7nsMzABHgB4B8ygFoZA2hhVWavhhGeURPJU9q45+17hGbfGxa82Ndex3hEM44SJGD2/b4AzDgGlHbl388AAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAAul8NnZ2f////82iC9AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEUAAAAAAAAul8NnZ2f/AAD7B+mqAAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAE9JREFUCNdljcsRACEIQ5MOiNKAdGAJ9N/Uiu7nsMzABHgB4B8ygFoZA2hhVWavhhGeURPJU9q45+17hGbfGxa82Ndex3hEM44SJGD2/b4AzDgGlHbl388AAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAElBMVEUBAAAAAABmzDNlyjJnZ2f///+6o7dfAAAAAXRSTlMAQObYZgAAAERJREFUeF6NjkEKADEIA51o///lJZfQxUsHITogWi8AvwZJuxmYa25xDooBLEwOWFTYAsYVhdorLZt9Ng9xCUTCUCQ2H3F4ANrZ2WNiAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEUAAAAAAABmzDNmZmb/AAC8/wCMAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE9JREFUCNdljcsRACEIQ5MOiNKAdGAJ9N/Uiu7nsMzABHgB4B8ygFoZA2hhVWavhhGeURPJU9q45+17hGbfGxa82Ndex3hEM44SJGD2/b4AzDgGlHbl388AAAAASUVORK5CYII='], - Original: ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX/////AAD///8AAABBZmS3AAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhElEQVR42q1RwQnAMAjMu5M4guAKXa4j5dUROo5tipSDcrFChUONd0di2m/hEGVOHDyIPufgwAFASDkpoSzmBrkJ2UMyR9LsJ3rvrqo3Rt1YMIMhhNnOxLMnoMFBxHyJAr2IOBFzA8U+6pLBdmEJTA0aMVjpDd6Loks0s5HZNwYx8tfZCZ0kll7ORffZAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX///8ul8P///8AAACaqgkzAAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAALVBMVEUAAAAAAAAAAAAAAAABBQcHFx4KISoNLToaVW4oKCgul8M4ODg7OzvBwcH///8uS/CdAAAAA3RSTlMAx9dmesIgAAAAV0lEQVR42m2NWw6AIBAD1eILZO5/XI0UAgm7H9tOsu0yGWAQSOoFijHOxOANGqm/LczpOaXs4gISrPZ+gc2+hO5w2xdwgOjBFUIF+sEJrhUl9JFr+badFwR+BfqlmGUJAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX///9mzDP///8AAACT0n1lAAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAALVBMVEUAAAAAAAAAAAAAAAAECAIQIAgWLAsePA8oKCg4ODg6dB07OztmzDPBwcH///+rsf3XAAAAA3RSTlMAx9dmesIgAAAAV0lEQVR42m2NWw6AIBAD1eIDhbn/cTVSCCTsfmw7ybbLZIBBIKkXKKU0E4M3aKT+tjCn5xiziwuIsNr7BTb7ErrDZV/AAaIHdwgV6AcnuFaU0Eeu5dt2XiUyBjCQ2bIrAAAAAElFTkSuQmCC'], - 'Metro': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAC/AABrZQDiAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAAC/AAD///8dAAApAABsAAAHAAA4AACQAAAsAABMCpCvAAAAA3RSTlMAPse+s4iwAAAAMklEQVQI12NggAFmY2MDECaNAQZCilAzVJyg5oS4GqAxUtygjIp2KGOKJ5SxepcB3BUAcdYRqxAtgFoAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAAA1/GhpCidAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAAAA1/H///8AISUALzQAeokACAkAQEcAorYAMTcE9WFNAAAAA3RSTlMAPse+s4iwAAAAMklEQVQI12NggAFmY2MDECaNAQZCilAzVJyg5oS4GqAxUtygjIp2KGOKJ5SxepcB3BUAcdYRqxAtgFoAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAABV/wErM5hwAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAABV/wH///8NKAASOAAwkQADCgAZTABAwQATOwC5e3VGAAAAA3RSTlMAPse+s4iwAAAAMklEQVQI12NggAFmY2MDECaNAQZCilAzVJyg5oS4GqAxUtygjIp2KGOKJ5SxepcB3BUAcdYRqxAtgFoAAAAASUVORK5CYII='] - }; - items = $.getOwn(items, Conf['favicon']); - f = Favicon; - t = 'data:image/png;base64,'; - i = 0; - while (items[i]) { - items[i] = t + items[i++]; - } - f.unreadDead = items[0], f.unreadDeadY = items[1], f.unreadSFW = items[2], f.unreadSFWY = items[3], f.unreadNSFW = items[4], f.unreadNSFWY = items[5]; - return f.update(); - }, - update: function() { - if (this.isSFW) { - this.unread = this.unreadSFW; - return this.unreadY = this.unreadSFWY; - } else { - this.unread = this.unreadNSFW; - return this.unreadY = this.unreadNSFWY; - } - }, - SFW: '//s.4cdn.org/image/favicon-ws.ico', - NSFW: '//s.4cdn.org/image/favicon.ico', - dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==', - logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACAAgMAAAC+UIlYAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAGlJREFUWMPtlkEKADEIA/tJP9lXLttQto2yHxgDHozTi0ToGK2WKZZ+HAQQMZc+xBwI4EZ+wAC2IfPuSIDOZJrSZQEAX9eVJhhwIuUYAnQe8rhAEMAZlTI2MID9f5Clyh0JeE1V1ZEAvB4qDfwuJTSGRAAAAABJRU5ErkJggg==' - }; - - return Favicon; - -}).call(this); - -MarkNewIPs = (function() { - var MarkNewIPs; - - MarkNewIPs = { - init: function() { - if (!(g.SITE.software === 'yotsuba' && g.VIEW === 'thread' && Conf['Mark New IPs'])) { - return; - } - return Callbacks.Thread.push({ - name: 'Mark New IPs', - cb: this.node - }); - }, - node: function() { - MarkNewIPs.ipCount = this.ipCount; - MarkNewIPs.postCount = this.posts.keys.length; - return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); - }, - onUpdate: function(e) { - var deletedPosts, fullID, i, ipCount, j, k, len, len1, newPosts, postCount, ref; - ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; - if (ipCount == null) { - return; - } - switch (ipCount - MarkNewIPs.ipCount) { - case postCount - MarkNewIPs.postCount + deletedPosts.length: - i = MarkNewIPs.ipCount; - for (j = 0, len = newPosts.length; j < len; j++) { - fullID = newPosts[j]; - MarkNewIPs.markNew(g.posts.get(fullID), ++i); - } - break; - case -deletedPosts.length: - for (k = 0, len1 = newPosts.length; k < len1; k++) { - fullID = newPosts[k]; - MarkNewIPs.markOld(g.posts.get(fullID)); - } - } - MarkNewIPs.ipCount = ipCount; - return MarkNewIPs.postCount = postCount; - }, - markNew: function(post, ipCount) { - var counter, suffix; - suffix = (Math.floor(ipCount / 10)) % 10 === 1 ? 'th' : ['st', 'nd', 'rd'][ipCount % 10 - 1] || 'th'; - counter = $.el('span', { - className: 'ip-counter', - textContent: "(" + ipCount + ")" - }); - post.nodes.nameBlock.title = "This is the " + ipCount + suffix + " IP in the thread."; - $.add(post.nodes.nameBlock, [$.tn(' '), counter]); - return $.addClass(post.nodes.root, 'new-ip'); - }, - markOld: function(post) { - post.nodes.nameBlock.title = 'Not the first post from this IP.'; - return $.addClass(post.nodes.root, 'old-ip'); - } - }; - - return MarkNewIPs; - -}).call(this); - -ReplyPruning = (function() { - var ReplyPruning; - - ReplyPruning = { - init: function() { - var el, label; - if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { - return; - } - this.container = $.frag(); - this.summary = $.el('span', { - hidden: true, - className: 'summary' - }); - this.summary.style.cursor = 'pointer'; - $.on(this.summary, 'click', (function(_this) { - return function() { - _this.inputs.enabled.checked = !_this.inputs.enabled.checked; - return $.event('change', null, _this.inputs.enabled); - }; - })(this)); - label = UI.checkbox('Prune Replies', 'Show Last', Conf['Prune All Threads']); - el = $.el('span', { - title: 'Maximum number of replies to show.' - }, {innerHTML: " "}); - $.prepend(el, label); - this.inputs = { - enabled: label.firstElementChild, - replies: el.lastElementChild - }; - this.setEnabled.call(this.inputs.enabled); - $.on(this.inputs.enabled, 'change', this.setEnabled); - $.on(this.inputs.replies, 'change', $.cb.value); - Header.menu.addEntry({ - el: el, - order: 190 - }); - return Callbacks.Thread.push({ - name: 'Reply Pruning', - cb: this.node - }); - }, - position: 0, - hidden: 0, - hiddenFiles: 0, - total: 0, - totalFiles: 0, - setEnabled: function() { - var other; - other = QuoteThreading.input; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return ReplyPruning.active = this.checked; - }, - showIfHidden: function(id) { - if (ReplyPruning.container && $("#" + id, ReplyPruning.container)) { - ReplyPruning.inputs.enabled.checked = false; - return $.event('change', null, ReplyPruning.inputs.enabled); - } - }, - node: function() { - var ref; - ReplyPruning.thread = this; - if (this.isSticky) { - ReplyPruning.active = ReplyPruning.inputs.enabled.checked = true; - if (QuoteThreading.input) { - Conf['Thread Quotes'] = QuoteThreading.input.checked = false; - } - } - this.posts.forEach(function(post) { - if (post.isReply) { - ReplyPruning.total++; - if (post.file) { - return ReplyPruning.totalFiles++; - } - } - }); - if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (1 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { - ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; - } - $.after(this.OP.nodes.root, ReplyPruning.summary); - $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); - $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); - $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); - $.on(d, 'ThreadUpdate', ReplyPruning.update); - return ReplyPruning.update(); - }, - updateCount: function(e) { - var fullID, i, len, ref; - if (e.detail[404]) { - return; - } - ref = e.detail.newPosts; - for (i = 0, len = ref.length; i < len; i++) { - fullID = ref[i]; - ReplyPruning.total++; - if (g.posts.get(fullID).file) { - ReplyPruning.totalFiles++; - } - } - }, - update: function() { - var boardTop, frag, hidden1, hidden2, node, oldPos, post, posts; - hidden1 = ReplyPruning.hidden; - hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; - oldPos = d.body.clientHeight - window.scrollY; - posts = ReplyPruning.thread.posts; - if (ReplyPruning.hidden < hidden2) { - while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { - post = posts.get(posts.keys[ReplyPruning.position++]); - if (post.isReply && !post.isFetchedQuote) { - while ((node = ReplyPruning.summary.nextSibling) && node !== post.nodes.root) { - $.add(ReplyPruning.container, node); - } - $.add(ReplyPruning.container, post.nodes.root); - ReplyPruning.hidden++; - if (post.file) { - ReplyPruning.hiddenFiles++; - } - } - } - } else if (ReplyPruning.hidden > hidden2) { - frag = $.frag(); - while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { - post = posts.get(posts.keys[--ReplyPruning.position]); - if (post.isReply && !post.isFetchedQuote) { - while ((node = ReplyPruning.container.lastChild) && node !== post.nodes.root) { - $.prepend(frag, node); - } - $.prepend(frag, post.nodes.root); - ReplyPruning.hidden--; - if (post.file) { - ReplyPruning.hiddenFiles--; - } - } - } - $.after(ReplyPruning.summary, frag); - $.event('PostsInserted', null, ReplyPruning.summary.parentNode); - } - ReplyPruning.summary.textContent = ReplyPruning.active ? g.SITE.Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : g.SITE.Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); - ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; - if (hidden1 !== hidden2 && (boardTop = Header.getTopOf($('.board'))) < 0) { - return window.scrollBy(0, Math.max(d.body.clientHeight - oldPos, window.scrollY + boardTop) - window.scrollY); - } - } - }; - - return ReplyPruning; - -}).call(this); - -ThreadStats = (function() { - var ThreadStats; - - ThreadStats = { - postCount: 0, - fileCount: 0, - postIndex: 0, - init: function() { - var base, sc, statsHTML, statsTitle; - if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { - return; - } - if (Conf['Page Count in Stats']) { - this[(typeof (base = g.SITE).isPrunedByAge === "function" ? base.isPrunedByAge(g.BOARD) : void 0) ? 'showPurgePos' : 'showPage'] = true; - } - statsHTML = {innerHTML: "? / ?" + ((Conf["IP Count in Stats"] && g.SITE.hasIPCount) ? " / ?" : "") + ((Conf["Page Count in Stats"]) ? " / ?" : "")}; - statsTitle = 'Posts / Files'; - if (Conf['IP Count in Stats'] && g.SITE.hasIPCount) { - statsTitle += ' / IPs'; - } - if (Conf['Page Count in Stats']) { - statsTitle += (this.showPurgePos ? ' / Purge Position' : ' / Page'); - } - if (Conf['Updater and Stats in Header']) { - this.dialog = sc = $.el('span', { - id: 'thread-stats', - title: statsTitle - }); - $.extend(sc, statsHTML); - Header.addShortcut('stats', sc, 200); - } else { - this.dialog = sc = UI.dialog('thread-stats', {innerHTML: "
    " + (statsHTML).innerHTML + "
    "}); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.postCountEl = $('#post-count', sc); - this.fileCountEl = $('#file-count', sc); - this.ipCountEl = $('#ip-count', sc); - this.pageCountEl = $('#page-count', sc); - if (this.pageCountEl) { - $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); - } - return Callbacks.Thread.push({ - name: 'Thread Stats', - cb: this.node - }); - }, - node: function() { - ThreadStats.thread = this; - ThreadStats.count(); - ThreadStats.update(); - ThreadStats.fetchPage(); - $.on(d, 'PostsInserted', function() { - return $.queueTask(ThreadStats.onPostsInserted); - }); - return $.on(d, 'ThreadUpdate', ThreadStats.onUpdate); - }, - count: function() { - var i, j, n, post, posts, ref, ref1; - posts = ThreadStats.thread.posts; - n = posts.keys.length; - for (i = j = ref = ThreadStats.postIndex, ref1 = n; j < ref1; i = j += 1) { - post = posts.get(posts.keys[i]); - if (!post.isFetchedQuote) { - ThreadStats.postCount++; - ThreadStats.fileCount += post.files.length; - } - } - return ThreadStats.postIndex = n; - }, - onUpdate: function(e) { - var fileCount, postCount, ref; - if (e.detail[404]) { - return; - } - ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount; - $.extend(ThreadStats, { - postCount: postCount, - fileCount: fileCount - }); - ThreadStats.postIndex = ThreadStats.thread.posts.keys.length; - ThreadStats.update(); - if (ThreadStats.showPage && ThreadStats.pageCountEl.textContent !== '1') { - return ThreadStats.fetchPage(); - } - }, - onPostsInserted: function() { - if (!(ThreadStats.thread.posts.keys.length > ThreadStats.postIndex)) { - return; - } - ThreadStats.count(); - ThreadStats.update(); - if (ThreadStats.showPage && ThreadStats.pageCountEl.textContent !== '1') { - return ThreadStats.fetchPage(); - } - }, - update: function() { - var fileCountEl, ipCountEl, postCountEl, ref, thread; - thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; - postCountEl.textContent = ThreadStats.postCount; - fileCountEl.textContent = ThreadStats.fileCount; - if (ipCountEl != null) { - ipCountEl.textContent = (ref = thread.ipCount) != null ? ref : '?'; - } - postCountEl.classList.toggle('warning', thread.postLimit && !thread.isSticky); - return fileCountEl.classList.toggle('warning', thread.fileLimit && !thread.isSticky); - }, - fetchPage: function() { - if (!ThreadStats.pageCountEl) { - return; - } - clearTimeout(ThreadStats.timeout); - if (ThreadStats.thread.isDead) { - ThreadStats.pageCountEl.textContent = 'Dead'; - $.addClass(ThreadStats.pageCountEl, 'warning'); - return; - } - ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 2 * $.MINUTE); - return $.whenModified(g.SITE.urls.threadsListJSON(ThreadStats.thread), 'ThreadStats', ThreadStats.onThreadsLoad); - }, - onThreadsLoad: function() { - var i, j, k, l, len, len1, len2, len3, len4, m, nThreads, o, page, pageNum, purgePos, ref, ref1, ref2, ref3, ref4, thread; - if (this.status === 200) { - if (ThreadStats.showPurgePos) { - purgePos = 1; - ref = this.response; - for (j = 0, len = ref.length; j < len; j++) { - page = ref[j]; - ref1 = page.threads; - for (k = 0, len1 = ref1.length; k < len1; k++) { - thread = ref1[k]; - if (thread.no < ThreadStats.thread.ID) { - purgePos++; - } - } - } - ThreadStats.pageCountEl.textContent = purgePos; - return ThreadStats.pageCountEl.classList.toggle('warning', purgePos === 1); - } else { - i = nThreads = 0; - ref2 = this.response; - for (l = 0, len2 = ref2.length; l < len2; l++) { - page = ref2[l]; - nThreads += page.threads.length; - } - ref3 = this.response; - for (pageNum = m = 0, len3 = ref3.length; m < len3; pageNum = ++m) { - page = ref3[pageNum]; - ref4 = page.threads; - for (o = 0, len4 = ref4.length; o < len4; o++) { - thread = ref4[o]; - if (thread.no === ThreadStats.thread.ID) { - ThreadStats.pageCountEl.textContent = pageNum + 1; - ThreadStats.pageCountEl.classList.toggle('warning', i >= nThreads - this.response[0].threads.length); - ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); - ThreadStats.retry(); - return; - } - i++; - } - } - } - } else if (this.status === 304) { - return ThreadStats.retry(); - } - }, - retry: function() { - if (!(ThreadStats.showPage && ThreadStats.pageCountEl.textContent !== '1' && !g.SITE.threadModTimeIgnoresSage && ThreadStats.thread.posts.get(ThreadStats.thread.lastPost).info.date > ThreadStats.lastPageUpdate)) { - return; - } - clearTimeout(ThreadStats.timeout); - return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); - } - }; - - return ThreadStats; - -}).call(this); - -ThreadUpdater = (function() { - var ThreadUpdater, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - ThreadUpdater = { - init: function() { - var conf, el, input, name, ref, sc, subEntries, updateLink; - if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { - return; - } - this.enabled = true; - this.audio = $.el('audio'); - if ($.engine !== 'gecko') { - this.audio.src = this.beep; - } - if (Conf['Updater and Stats in Header']) { - this.dialog = sc = $.el('span', { - id: 'updater' - }); - $.extend(sc, {innerHTML: ""}); - Header.addShortcut('updater', sc, 100); - } else { - this.dialog = sc = UI.dialog('updater', {innerHTML: "
    "}); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.checkPostCount = 0; - this.timer = $('#update-timer', sc); - this.status = $('#update-status', sc); - $.on(this.timer, 'click', this.update); - $.on(this.status, 'click', this.update); - updateLink = $.el('span', { - className: 'brackets-wrap updatelink' - }); - $.extend(updateLink, {innerHTML: "Update"}); - Main.ready(function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - return $.add(navLinksBot, [$.tn(' '), updateLink]); - } - }); - $.on(updateLink.firstElementChild, 'click', this.update); - subEntries = []; - ref = Config.updater.checkbox; - for (name in ref) { - conf = ref[name]; - el = UI.checkbox(name, name); - el.title = conf[1]; - input = el.firstElementChild; - $.on(input, 'change', $.cb.checked); - if (input.name === 'Scroll BG') { - $.on(input, 'change', this.cb.scrollBG); - this.cb.scrollBG(); - } else if (input.name === 'Auto Update') { - $.on(input, 'change', this.setInterval); - } - subEntries.push({ - el: el - }); - } - this.settings = $.el('span', {innerHTML: "Interval"}); - $.on(this.settings, 'click', this.intervalShortcut); - subEntries.push({ - el: this.settings - }); - Header.menu.addEntry(this.entry = { - el: $.el('span', { - textContent: 'Updater' - }), - order: 110, - subEntries: subEntries - }); - return Callbacks.Thread.push({ - name: 'Thread Updater', - cb: this.node - }); - }, - node: function() { - ThreadUpdater.thread = this; - ThreadUpdater.root = this.nodes.root; - ThreadUpdater.outdateCount = 0; - ThreadUpdater.postIDs = []; - ThreadUpdater.fileIDs = []; - this.posts.forEach(function(post) { - ThreadUpdater.postIDs.push(post.ID); - if (post.file) { - return ThreadUpdater.fileIDs.push(post.ID); - } - }); - ThreadUpdater.cb.interval.call($.el('input', { - value: Conf['Interval'] - })); - $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); - $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - return ThreadUpdater.setInterval(); - }, - - /* - http://freesound.org/people/pierrecartoons1979/sounds/90112/ - cc-by-nc-3.0 - */ - beep: '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', - playBeep: function() { - var audio; - audio = ThreadUpdater.audio; - audio.src || (audio.src = ThreadUpdater.beep); - if (audio.paused) { - return audio.play(); - } else { - return $.one(audio, 'ended', ThreadUpdater.playBeep); - } - }, - cb: { - checkpost: function(e) { - if (e.detail.threadID !== ThreadUpdater.thread.ID) { - return; - } - ThreadUpdater.postID = e.detail.postID; - ThreadUpdater.checkPostCount = 0; - ThreadUpdater.outdateCount = 0; - return ThreadUpdater.setInterval(); - }, - visibility: function() { - if (d.hidden) { - return; - } - ThreadUpdater.outdateCount = 0; - if (ThreadUpdater.seconds > ThreadUpdater.interval) { - return ThreadUpdater.setInterval(); - } - }, - scrollBG: function() { - return ThreadUpdater.scrollBG = Conf['Scroll BG'] ? function() { - return true; - } : function() { - return !d.hidden; - }; - }, - interval: function(e) { - var val; - val = parseInt(this.value, 10); - if (val < 1) { - val = 1; - } - ThreadUpdater.interval = this.value = val; - if (e) { - return $.cb.value.call(this); - } - }, - load: function() { - if (this !== ThreadUpdater.req) { - return; - } - switch (this.status) { - case 200: - ThreadUpdater.parse(this); - if (ThreadUpdater.thread.isArchived) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.setInterval(); - } - break; - case 404: - return $.ajax(g.SITE.urls.catalogJSON({ - boardID: ThreadUpdater.thread.board.ID - }), { - onloadend: function() { - var confirmed, i, k, len, len1, page, ref, ref1, thread; - if (this.status === 200) { - confirmed = true; - ref = this.response; - for (i = 0, len = ref.length; i < len; i++) { - page = ref[i]; - ref1 = page.threads; - for (k = 0, len1 = ref1.length; k < len1; k++) { - thread = ref1[k]; - if (thread.no === ThreadUpdater.thread.ID) { - confirmed = false; - break; - } - } - } - } else { - confirmed = false; - } - if (confirmed) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.error(this); - } - } - }); - default: - return ThreadUpdater.error(this); - } - } - }, - kill: function() { - ThreadUpdater.thread.kill(); - ThreadUpdater.setInterval(); - return $.event('ThreadUpdate', { - 404: true, - threadID: ThreadUpdater.thread.fullID - }); - }, - error: function(req) { - if (req.status === 304) { - ThreadUpdater.set('status', ''); - } - ThreadUpdater.setInterval(); - if (!req.status) { - return ThreadUpdater.set('status', 'Connection Error', 'warning'); - } else if (req.status !== 304) { - return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); - } - }, - setInterval: function() { - var cur, interval, j, limit; - clearTimeout(ThreadUpdater.timeoutID); - if (ThreadUpdater.thread.isDead) { - ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); - ThreadUpdater.set('timer', ''); - return; - } - if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { - ThreadUpdater.set('timer', '...', 'loading'); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); - return; - } - if (!Conf['Auto Update']) { - ThreadUpdater.set('timer', 'Update'); - return; - } - interval = ThreadUpdater.interval; - if (Conf['Optional Increase']) { - limit = d.hidden ? 10 : 5; - j = Math.min(ThreadUpdater.outdateCount, limit); - cur = (Math.floor(interval * 0.1) || 1) * j * j; - ThreadUpdater.seconds = $.minmax(cur, interval, 300); - } else { - ThreadUpdater.seconds = interval; - } - return ThreadUpdater.timeout(); - }, - intervalShortcut: function() { - var settings; - Settings.open('Advanced'); - settings = $.id('fourchanx-settings'); - return $('input[name=Interval]', settings).focus(); - }, - set: function(name, text, klass) { - var el, node; - el = ThreadUpdater[name]; - if (node = el.firstChild) { - node.data = text; - } else { - el.textContent = text; - } - return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); - }, - timeout: function() { - if (ThreadUpdater.seconds) { - ThreadUpdater.set('timer', ThreadUpdater.seconds); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); - } else { - ThreadUpdater.outdateCount++; - ThreadUpdater.update(); - } - return ThreadUpdater.seconds--; - }, - update: function() { - var oldReq; - clearTimeout(ThreadUpdater.timeoutID); - ThreadUpdater.set('timer', '...', 'loading'); - if ((oldReq = ThreadUpdater.req)) { - delete ThreadUpdater.req; - oldReq.abort(); - } - return ThreadUpdater.req = $.whenModified(g.SITE.urls.threadJSON({ - boardID: ThreadUpdater.thread.board.ID, - threadID: ThreadUpdater.thread.ID - }), 'ThreadUpdater', ThreadUpdater.cb.load, { - timeout: $.MINUTE - }); - }, - updateThreadStatus: function(type, status) { - var change, hasChanged; - if (!(hasChanged = ThreadUpdater.thread["is" + type] !== status)) { - return; - } - ThreadUpdater.thread.setStatus(type, status); - if (type === 'Closed' && ThreadUpdater.thread.isArchived) { - return; - } - change = type === 'Sticky' ? status ? 'now a sticky' : 'not a sticky anymore' : status ? 'now closed' : 'not closed anymore'; - return new Notice('info', "The thread is " + change + ".", 30); - }, - parse: function(req) { - var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, i, index, ipCountEl, k, l, lastPost, len, len1, len2, len3, m, newPosts, node, post, postObject, postObjects, posts, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, unreadCount, unreadQYCount; - postObjects = req.response.posts; - OP = postObjects[0]; - thread = ThreadUpdater.thread; - board = thread.board; - ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; - if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts.get(lastPost).info.date < 30 * $.SECOND) { - return; - } - g.SITE.Build.spoilerRange[board] = OP.custom_spoiler; - thread.setStatus('Archived', !!OP.archived); - ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); - ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); - thread.postLimit = !!OP.bumplimit; - thread.fileLimit = !!OP.imagelimit; - if (OP.unique_ips != null) { - thread.ipCount = OP.unique_ips; - } - posts = []; - index = []; - files = []; - newPosts = []; - for (i = 0, len = postObjects.length; i < len; i++) { - postObject = postObjects[i]; - ID = postObject.no; - index.push(ID); - if (postObject.fsize) { - files.push(ID); - } - if (ID <= lastPost) { - continue; - } - if ((post = thread.posts.get(ID)) && !post.isFetchedQuote) { - post.resurrect(); - continue; - } - newPosts.push(board + "." + ID); - node = g.SITE.Build.postFromObject(postObject, board.ID); - posts.push(new Post(node, thread, board)); - if (ThreadUpdater.postID === ID) { - delete ThreadUpdater.postID; - } - } - deletedPosts = []; - ref1 = ThreadUpdater.postIDs; - for (k = 0, len1 = ref1.length; k < len1; k++) { - ID = ref1[k]; - if (!(indexOf.call(index, ID) < 0)) { - continue; - } - thread.posts.get(ID).kill(); - deletedPosts.push(board + "." + ID); - } - ThreadUpdater.postIDs = index; - deletedFiles = []; - ref2 = ThreadUpdater.fileIDs; - for (l = 0, len2 = ref2.length; l < len2; l++) { - ID = ref2[l]; - if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { - continue; - } - thread.posts.get(ID).kill(true); - deletedFiles.push(board + "." + ID); - } - ThreadUpdater.fileIDs = files; - if (!posts.length) { - ThreadUpdater.set('status', ''); - } else { - ThreadUpdater.set('status', "+" + posts.length, 'new'); - ThreadUpdater.outdateCount = 0; - unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; - unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; - Main.callbackNodes('Post', posts); - if (d.hidden || !d.hasFocus()) { - if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { - ThreadUpdater.playBeep(); - if (Conf['Beep']) { - ThreadUpdater.playBeep(); - } - } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { - ThreadUpdater.playBeep(); - } - } - scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; - firstPost = null; - for (m = 0, len3 = posts.length; m < len3; m++) { - post = posts[m]; - if (!QuoteThreading.insert(post)) { - firstPost || (firstPost = post.nodes.root); - $.add(ThreadUpdater.root, post.nodes.root); - } - } - $.event('PostsInserted', null, ThreadUpdater.root); - if (scroll) { - if (Conf['Bottom Scroll']) { - window.scrollTo(0, d.body.clientHeight); - } else { - if (firstPost) { - Header.scrollTo(firstPost); - } - } - } - } - if ((OP.unique_ips != null) && (ipCountEl = $.id('unique-ips'))) { - ipCountEl.textContent = OP.unique_ips; - ipCountEl.previousSibling.textContent = ipCountEl.previousSibling.textContent.replace(/\b(?:is|are)\b/, OP.unique_ips === 1 ? 'is' : 'are'); - ipCountEl.nextSibling.textContent = ipCountEl.nextSibling.textContent.replace(/\bposters?\b/, OP.unique_ips === 1 ? 'poster' : 'posters'); - } - return $.event('ThreadUpdate', { - 404: false, - threadID: thread.fullID, - newPosts: newPosts, - deletedPosts: deletedPosts, - deletedFiles: deletedFiles, - postCount: OP.replies + 1, - fileCount: OP.images + !!OP.fsize, - ipCount: OP.unique_ips - }); - } - }; - - return ThreadUpdater; - -}).call(this); - -ThreadWatcher = (function() { - var ThreadWatcher, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - ThreadWatcher = { - init: function() { - var ref, sc; - if (!(this.enabled = Conf['Thread Watcher'])) { - return; - } - this.shortcut = sc = $.el('a', { - id: 'watcher-link', - textContent: 'Watcher', - title: 'Thread Watcher', - href: 'javascript:;', - className: 'fa fa-eye' - }); - this.db = new DataBoard('watchedThreads', this.refresh, true); - this.dbLM = new DataBoard('watcherLastModified', null, true); - this.dialog = UI.dialog('thread-watcher', {innerHTML: "
    Thread Watcher ×
    "}); - this.status = $('#watcher-status', this.dialog); - this.list = this.dialog.lastElementChild; - this.refreshButton = $('.refresh', this.dialog); - this.closeButton = $('.move > .close', this.dialog); - this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts'); - this.unreadEnabled = Conf['Remember Last Read Post']; - $.on(d, 'QRPostSuccessful', this.cb.post); - $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.buttonFetchAll); - $.on(this.closeButton, 'click', this.toggleWatcher); - this.menu.addHeaderMenuEntry(); - $.onExists(doc, 'body', this.addDialog); - switch (g.VIEW) { - case 'index': - $.on(d, 'IndexUpdate', this.cb.onIndexUpdate); - break; - case 'thread': - $.on(d, 'ThreadUpdate', this.cb.onThreadRefresh); - } - if (Conf['Fixed Thread Watcher']) { - $.addClass(doc, 'fixed-watcher'); - } - if (!Conf['Persistent Thread Watcher']) { - $.addClass(ThreadWatcher.shortcut, 'disabled'); - this.dialog.hidden = true; - } - Header.addShortcut('watcher', sc, 510); - ThreadWatcher.initLastModified(); - ThreadWatcher.fetchAuto(); - $.on(window, 'visibilitychange focus', function() { - return $.queueTask(ThreadWatcher.fetchAuto); - }); - if (Conf['Menu'] && Index.enabled) { - Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, {innerHTML: "Alt+click"}), - order: 6, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; - if (this.cb) { - $.off(this.el, 'click', this.cb); - } - this.cb = function() { - $.event('CloseMenu'); - return ThreadWatcher.toggle(thread); - }; - $.on(this.el, 'click', this.cb); - return true; - } - }); - } - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - Callbacks.Post.push({ - name: 'Thread Watcher', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Thread Watcher', - cb: this.catalogNode - }); - }, - isWatched: function(thread) { - var ref; - return !!((ref = ThreadWatcher.db) != null ? ref.get({ - boardID: thread.board.ID, - threadID: thread.ID - }) : void 0); - }, - isWatchedRaw: function(boardID, threadID) { - var ref; - return !!((ref = ThreadWatcher.db) != null ? ref.get({ - boardID: boardID, - threadID: threadID - }) : void 0); - }, - setToggler: function(toggler, isWatched) { - toggler.classList.toggle('watched', isWatched); - return toggler.title = (isWatched ? 'Unwatch' : 'Watch') + " Thread"; - }, - node: function() { - var boardID, data, siteID, threadID, toggler; - if (this.isReply) { - return; - } - if (this.isClone) { - toggler = $('.watch-thread-link', this.nodes.info); - } else { - toggler = $.el('a', { - href: 'javascript:;', - className: 'watch-thread-link' - }); - $.before($('input', this.nodes.info), toggler); - } - siteID = g.SITE.ID; - boardID = this.board.ID; - threadID = this.thread.ID; - data = ThreadWatcher.db.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }); - ThreadWatcher.setToggler(toggler, !!data); - $.on(toggler, 'click', ThreadWatcher.cb.toggle); - if (data && (data.excerpt == null)) { - return $.queueTask((function(_this) { - return function() { - return ThreadWatcher.update(siteID, boardID, threadID, { - excerpt: Get.threadExcerpt(_this.thread) - }); - }; - })(this)); - } - }, - catalogNode: function() { - if (ThreadWatcher.isWatched(this.thread)) { - $.addClass(this.nodes.root, 'watched'); - } - return $.on(this.nodes.root, 'mousedown click', (function(_this) { - return function(e) { - if (!(e.button === 0 && e.altKey)) { - return; - } - if (e.type === 'click') { - ThreadWatcher.toggle(_this.thread); - } - return e.preventDefault(); - }; - })(this)); - }, - addDialog: function() { - if (!Main.isThisPageLegit()) { - return; - } - ThreadWatcher.build(); - return $.prepend(d.body, ThreadWatcher.dialog); - }, - toggleWatcher: function() { - $.toggleClass(ThreadWatcher.shortcut, 'disabled'); - return ThreadWatcher.dialog.hidden = !ThreadWatcher.dialog.hidden; - }, - cb: { - openAll: function() { - var a, j, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('a.watcher-link', ThreadWatcher.list); - for (j = 0, len1 = ref.length; j < len1; j++) { - a = ref[j]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - openUnread: function() { - var a, j, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('.replies-unread > a.watcher-link', ThreadWatcher.list); - for (j = 0, len1 = ref.length; j < len1; j++) { - a = ref[j]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - openDeads: function() { - var a, j, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('.dead-thread > a.watcher-link', ThreadWatcher.list); - for (j = 0, len1 = ref.length; j < len1; j++) { - a = ref[j]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - pruneDeads: function() { - var boardID, data, j, len1, ref, ref1, siteID, threadID; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = ThreadWatcher.getAll(); - for (j = 0, len1 = ref.length; j < len1; j++) { - ref1 = ref[j], siteID = ref1.siteID, boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; - if (data.isDead) { - ThreadWatcher.db["delete"]({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }); - } - } - ThreadWatcher.refresh(); - return $.event('CloseMenu'); - }, - dismiss: function() { - var boardID, data, j, len1, ref, ref1, siteID, threadID; - ref = ThreadWatcher.getAll(); - for (j = 0, len1 = ref.length; j < len1; j++) { - ref1 = ref[j], siteID = ref1.siteID, boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; - if (data.quotingYou) { - ThreadWatcher.update(siteID, boardID, threadID, { - dismiss: data.quotingYou || 0 - }); - } - } - return $.event('CloseMenu'); - }, - toggle: function() { - var thread; - thread = Get.postFromNode(this).thread; - return ThreadWatcher.toggle(thread); - }, - rm: function() { - var boardID, ref, siteID, threadID; - siteID = this.parentNode.dataset.siteID; - ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; - return ThreadWatcher.rm(siteID, boardID, +threadID); - }, - post: function(e) { - var boardID, cb, postID, ref, threadID; - ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - cb = PostRedirect.delay(); - if (postID === threadID) { - if (Conf['Auto Watch']) { - return ThreadWatcher.addRaw(boardID, threadID, {}, cb); - } - } else if (Conf['Auto Watch Reply']) { - return ThreadWatcher.add(g.threads.get(boardID + '.' + threadID) || new Thread(threadID, g.boards[boardID] || new Board(boardID)), cb); - } - }, - onIndexUpdate: function(e) { - var boardID, data, db, nKilled, ref, ref1, siteID, threadID; - db = ThreadWatcher.db; - siteID = g.SITE.ID; - boardID = g.BOARD.ID; - nKilled = 0; - ref = db.data[siteID].boards[boardID]; - for (threadID in ref) { - data = ref[threadID]; - if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) { - continue; - } - if (!e.detail.threads.some(function(fullID) { - return +fullID.split('.')[1] > threadID; - })) { - continue; - } - if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - db["delete"]({ - boardID: boardID, - threadID: threadID - }); - nKilled++; - } else { - ThreadWatcher.fetchStatus({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - data: data - }); - } - } - if (nKilled) { - return ThreadWatcher.refresh(); - } - }, - onThreadRefresh: function(e) { - var thread; - thread = g.threads.get(e.detail.threadID); - if (!(e.detail[404] && ThreadWatcher.isWatched(thread))) { - return; - } - return ThreadWatcher.add(thread); - } - }, - requests: [], - fetched: 0, - fetch: function(url, arg, args, cb) { - var ajax, force, onloadend, ref, req, siteID; - siteID = arg.siteID, force = arg.force; - if (ThreadWatcher.requests.length === 0) { - ThreadWatcher.status.textContent = '...'; - $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); - } - onloadend = function() { - if (this.finished) { - return; - } - this.finished = true; - ThreadWatcher.fetched++; - if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { - ThreadWatcher.clearRequests(); - } else { - ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; - } - return cb.apply(this, args); - }; - ajax = siteID === g.SITE.ID ? $.ajax : CrossOrigin.ajax; - if (force) { - if ((ref = $.lastModified.ThreadWatcher) != null) { - delete ref[url]; - } - } - req = $.whenModified(url, 'ThreadWatcher', onloadend, { - timeout: $.MINUTE, - ajax: ajax - }); - return ThreadWatcher.requests.push(req); - }, - clearRequests: function() { - ThreadWatcher.requests = []; - ThreadWatcher.fetched = 0; - ThreadWatcher.status.textContent = ''; - return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); - }, - abort: function() { - var j, len1, ref, req; - delete ThreadWatcher.syncing; - ref = ThreadWatcher.requests; - for (j = 0, len1 = ref.length; j < len1; j++) { - req = ref[j]; - if (!(!req.finished)) { - continue; - } - req.finished = true; - req.abort(); - } - return ThreadWatcher.clearRequests(); - }, - initLastModified: function() { - var base, boardID, boards, data, date, lm, ref, ref1, siteID, url; - lm = ((base = $.lastModified)['ThreadWatcher'] || (base['ThreadWatcher'] = $.dict())); - ref = ThreadWatcher.dbLM.data; - for (siteID in ref) { - boards = ref[siteID]; - ref1 = boards.boards; - for (boardID in ref1) { - data = ref1[boardID]; - if (ThreadWatcher.db.get({ - siteID: siteID, - boardID: boardID - })) { - for (url in data) { - date = data[url]; - lm[url] = date; - } - } else { - ThreadWatcher.dbLM["delete"]({ - siteID: siteID, - boardID: boardID - }); - } - } - } - }, - fetchAuto: function() { - var db, interval, now, ref; - clearTimeout(ThreadWatcher.timeout); - if (!Conf['Auto Update Thread Watcher']) { - return; - } - db = ThreadWatcher.db; - interval = Conf['Show Page'] || (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) ? 5 * $.MINUTE : 2 * $.HOUR; - now = Date.now(); - if (!((now - interval < (ref = db.data.lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) { - ThreadWatcher.fetchAllStatus(interval); - } - return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); - }, - buttonFetchAll: function() { - if (ThreadWatcher.syncing || ThreadWatcher.requests.length) { - return ThreadWatcher.abort(); - } else { - return ThreadWatcher.fetchAllStatus(); - } - }, - fetchAllStatus: function(interval) { - var dbi, dbs, j, len1, n, results; - if (interval == null) { - interval = 0; - } - ThreadWatcher.status.textContent = '...'; - $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); - ThreadWatcher.syncing = true; - dbs = [ThreadWatcher.db, ThreadWatcher.unreaddb, QuoteYou.db].filter(function(x) { - return x; - }); - n = 0; - results = []; - for (j = 0, len1 = dbs.length; j < len1; j++) { - dbi = dbs[j]; - results.push(dbi.forceSync(function() { - var board, boards, db, deep, k, len2, now, ref, ref1; - if ((++n) === dbs.length) { - if (!ThreadWatcher.syncing) { - return; - } - delete ThreadWatcher.syncing; - if (!((0 <= (ref = Date.now() - (ThreadWatcher.db.data.lastChecked || 0)) && ref < interval))) { - db = ThreadWatcher.db; - now = Date.now(); - deep = !((now - 2 * $.HOUR < (ref1 = db.data.lastChecked2 || 0) && ref1 <= now)); - boards = ThreadWatcher.getAll(true); - for (k = 0, len2 = boards.length; k < len2; k++) { - board = boards[k]; - ThreadWatcher.fetchBoard(board, deep); - } - db.setLastChecked(); - if (deep) { - db.setLastChecked('lastChecked2'); - } - } - if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { - return ThreadWatcher.clearRequests(); - } - } - })); - } - return results; - }, - fetchBoard: function(board, deep) { - var base, boardID, data, force, j, len1, ref, site, siteID, thread, url, urlF; - if (!board.some(function(thread) { - return !thread.data.isDead; - })) { - return; - } - force = false; - for (j = 0, len1 = board.length; j < len1; j++) { - thread = board[j]; - data = thread.data; - if (!data.isDead && data.last !== -1) { - if (Conf['Show Page'] && (data.page == null)) { - force = true; - } - if (data.modified == null) { - force = thread.force = true; - } - } - } - ref = board[0], siteID = ref.siteID, boardID = ref.boardID; - site = g.sites[siteID]; - if (!site) { - return; - } - urlF = deep && site.threadModTimeIgnoresSage ? 'catalogJSON' : 'threadsListJSON'; - url = typeof (base = site.urls)[urlF] === "function" ? base[urlF]({ - siteID: siteID, - boardID: boardID - }) : void 0; - if (!url) { - return; - } - return ThreadWatcher.fetch(url, { - siteID: siteID, - force: force - }, [board, url], ThreadWatcher.parseBoard); - }, - parseBoard: function(board, url) { - var base, boardID, data, i, index, item, j, k, l, lastPage, len1, len2, len3, len4, lmDate, m, modified, nThreads, oldest, page, pageLength, ref, ref1, ref2, ref3, ref4, replies, siteID, thread, threadID, threads; - if (this.status !== 200) { - return; - } - ref = board[0], siteID = ref.siteID, boardID = ref.boardID; - lmDate = this.getResponseHeader('Last-Modified'); - ThreadWatcher.dbLM.extend({ - siteID: siteID, - boardID: boardID, - val: $.item(url, lmDate) - }); - threads = $.dict(); - pageLength = 0; - nThreads = 0; - oldest = null; - try { - pageLength = ((ref1 = this.response[0]) != null ? ref1.threads.length : void 0) || 0; - ref2 = this.response; - for (i = j = 0, len1 = ref2.length; j < len1; i = ++j) { - page = ref2[i]; - ref3 = page.threads; - for (k = 0, len2 = ref3.length; k < len2; k++) { - item = ref3[k]; - threads[item.no] = { - page: i + 1, - index: nThreads, - modified: item.last_modified, - replies: item.replies - }; - nThreads++; - if ((oldest == null) || item.no < oldest) { - oldest = item.no; - } - } - } - } catch (error) { - for (l = 0, len3 = board.length; l < len3; l++) { - thread = board[l]; - ThreadWatcher.fetchStatus(thread); - } - } - for (m = 0, len4 = board.length; m < len4; m++) { - thread = board[m]; - threadID = thread.threadID, data = thread.data; - if (threads[threadID]) { - ref4 = threads[threadID], page = ref4.page, index = ref4.index, modified = ref4.modified, replies = ref4.replies; - if (Conf['Show Page']) { - lastPage = (typeof (base = g.sites[siteID]).isPrunedByAge === "function" ? base.isPrunedByAge({ - siteID: siteID, - boardID: boardID - }) : void 0) ? threadID === oldest : index >= nThreads - pageLength; - ThreadWatcher.update(siteID, boardID, threadID, { - page: page, - lastPage: lastPage - }); - } - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - if (modified !== data.modified || ((replies != null) && replies !== data.replies)) { - (thread.newData || (thread.newData = {})).modified = modified; - ThreadWatcher.fetchStatus(thread); - } - } - } else { - ThreadWatcher.fetchStatus(thread); - } - } - }, - fetchStatus: function(thread) { - var base, boardID, data, force, ref, siteID, threadID, url; - siteID = thread.siteID, boardID = thread.boardID, threadID = thread.threadID, data = thread.data, force = thread.force; - url = (ref = g.sites[siteID]) != null ? typeof (base = ref.urls).threadJSON === "function" ? base.threadJSON({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }) : void 0 : void 0; - if (!url) { - return; - } - if (data.isDead && !force) { - return; - } - if (data.last === -1) { - return; - } - return ThreadWatcher.fetch(url, { - siteID: siteID, - force: force - }, [thread], ThreadWatcher.parseStatus); - }, - parseStatus: function(thread, isArchiveURL) { - var archiveURL, base, boardID, data, force, isArchived, isDead, j, last, lastReadPost, len1, match, newData, postObj, quotesYou, quotingYou, ref, ref1, ref2, ref3, regexp, replies, site, siteID, threadID, unread, youOP; - siteID = thread.siteID, boardID = thread.boardID, threadID = thread.threadID, data = thread.data, newData = thread.newData, force = thread.force; - site = g.sites[siteID]; - if (this.status === 200 && this.response) { - last = this.response.posts[this.response.posts.length - 1].no; - replies = this.response.posts.length - 1; - isDead = isArchived = !!(this.response.posts[0].archived || isArchiveURL); - if (isDead && Conf['Auto Prune']) { - ThreadWatcher.rm(siteID, boardID, threadID); - return; - } - if (last === data.last && isDead === data.isDead && isArchived === data.isArchived) { - return; - } - lastReadPost = ThreadWatcher.unreaddb.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - defaultValue: 0 - }); - unread = data.unread || 0; - quotingYou = data.quotingYou || 0; - youOP = !!((ref = QuoteYou.db) != null ? ref.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: threadID - }) : void 0); - ref1 = this.response.posts; - for (j = 0, len1 = ref1.length; j < len1; j++) { - postObj = ref1[j]; - if (!(postObj.no > (data.last || 0) && postObj.no > lastReadPost)) { - continue; - } - if ((ref2 = QuoteYou.db) != null ? ref2.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: postObj.no - }) : void 0) { - continue; - } - quotesYou = false; - if (!Conf['Require OP Quote Link'] && youOP) { - quotesYou = true; - } else if (QuoteYou.db && postObj.com) { - regexp = site.regexp.quotelinkHTML; - regexp.lastIndex = 0; - while ((match = regexp.exec(postObj.com))) { - if (QuoteYou.db.get({ - siteID: siteID, - boardID: match[1] ? encodeURIComponent(match[1]) : boardID, - threadID: match[2] || threadID, - postID: match[3] || match[2] || threadID - })) { - quotesYou = true; - break; - } - } - } - if (!unread || (!quotingYou && quotesYou)) { - if (Filter.isHidden(site.Build.parseJSON(postObj, { - siteID: siteID, - boardID: boardID - }))) { - continue; - } - } - unread++; - if (quotesYou) { - quotingYou = postObj.no; - } - } - newData || (newData = {}); - $.extend(newData, { - last: last, - replies: replies, - isDead: isDead, - isArchived: isArchived, - unread: unread, - quotingYou: quotingYou - }); - return ThreadWatcher.update(siteID, boardID, threadID, newData); - } else if (this.status === 404) { - archiveURL = (ref3 = g.sites[siteID]) != null ? typeof (base = ref3.urls).archivedThreadJSON === "function" ? base.archivedThreadJSON({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }) : void 0 : void 0; - if (!isArchiveURL && archiveURL) { - return ThreadWatcher.fetch(archiveURL, { - siteID: siteID, - force: force - }, [thread, true], ThreadWatcher.parseStatus); - } else if (site.mayLackJSON && (data.last == null)) { - return ThreadWatcher.update(siteID, boardID, threadID, { - last: -1 - }); - } else { - return ThreadWatcher.update(siteID, boardID, threadID, { - isDead: true - }); - } - } - }, - getAll: function(groupByBoard) { - var all, boardID, boards, cont, data, ref, ref1, siteID, threadID, threads; - all = []; - ref = ThreadWatcher.db.data; - for (siteID in ref) { - boards = ref[siteID]; - ref1 = boards.boards; - for (boardID in ref1) { - threads = ref1[boardID]; - if (Conf['Current Board'] && (siteID !== g.SITE.ID || boardID !== g.BOARD.ID)) { - continue; - } - if (groupByBoard) { - all.push((cont = [])); - } - for (threadID in threads) { - data = threads[threadID]; - if (data && typeof data === 'object') { - (groupByBoard ? cont : all).push({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - data: data - }); - } - } - } - } - return all; - }, - makeLine: function(siteID, boardID, threadID, data) { - var count, div, excerpt, fullID, isArchived, link, page, ref, title, x; - x = $.el('a', { - className: 'fa fa-times', - href: 'javascript:;' - }); - $.on(x, 'click', ThreadWatcher.cb.rm); - excerpt = data.excerpt, isArchived = data.isArchived; - excerpt || (excerpt = "/" + boardID + "/ - No." + threadID); - if (Conf['Show Site Prefix']) { - excerpt = ThreadWatcher.prefixes[siteID] + excerpt; - } - link = $.el('a', { - href: ((ref = g.sites[siteID]) != null ? ref.urls.thread({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }, isArchived) : void 0) || '', - title: excerpt, - className: 'watcher-link' - }); - if (Conf['Show Page'] && (data.page != null)) { - page = $.el('span', { - textContent: "[" + data.page + "]", - className: 'watcher-page' - }); - $.add(link, page); - } - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && (data.unread != null)) { - count = $.el('span', { - textContent: "(" + data.unread + ")", - className: 'watcher-unread' - }); - $.add(link, count); - } - title = $.el('span', { - textContent: excerpt, - className: 'watcher-title' - }); - $.add(link, title); - div = $.el('div'); - fullID = boardID + "." + threadID; - div.dataset.fullID = fullID; - div.dataset.siteID = siteID; - if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) { - $.addClass(div, 'current'); - } - if (data.isDead) { - $.addClass(div, 'dead-thread'); - } - if (Conf['Show Page']) { - if (data.lastPage) { - $.addClass(div, 'last-page'); - } - if (data.page != null) { - div.dataset.page = data.page; - } - } - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - if (data.unread === 0) { - $.addClass(div, 'replies-read'); - } - if (data.unread) { - $.addClass(div, 'replies-unread'); - } - if ((data.quotingYou || 0) > (data.dismiss || 0)) { - $.addClass(div, 'replies-quoting-you'); - } - } - $.add(div, [x, $.tn(' '), link]); - return div; - }, - setPrefixes: function(threads) { - var conflicts, conflicts2, j, k, len, len1, len2, prefix, prefixes, siteID, siteID2; - prefixes = $.dict(); - for (j = 0, len1 = threads.length; j < len1; j++) { - siteID = threads[j].siteID; - if (siteID in prefixes) { - continue; - } - len = 0; - prefix = ''; - conflicts = Object.keys(prefixes); - while (conflicts.length > 0) { - len++; - prefix = siteID.slice(0, len); - conflicts2 = []; - for (k = 0, len2 = conflicts.length; k < len2; k++) { - siteID2 = conflicts[k]; - if (siteID2.slice(0, len) === prefix) { - conflicts2.push(siteID2); - } else if (prefixes[siteID2].length < len) { - prefixes[siteID2] = siteID2.slice(0, len); - } - } - conflicts = conflicts2; - } - prefixes[siteID] = prefix; - } - return ThreadWatcher.prefixes = prefixes; - }, - build: function() { - var boardID, data, j, len1, list, nodes, ref, siteID, thread, threadID, threads; - nodes = []; - threads = ThreadWatcher.getAll(); - ThreadWatcher.setPrefixes(threads); - for (j = 0, len1 = threads.length; j < len1; j++) { - ref = threads[j], siteID = ref.siteID, boardID = ref.boardID, threadID = ref.threadID, data = ref.data; - if ((data.excerpt == null) && siteID === g.SITE.ID && (thread = g.threads.get(boardID + "." + threadID)) && thread.OP) { - ThreadWatcher.db.extend({ - boardID: boardID, - threadID: threadID, - val: { - excerpt: Get.threadExcerpt(thread) - } - }); - } - nodes.push(ThreadWatcher.makeLine(siteID, boardID, threadID, data)); - } - list = ThreadWatcher.list; - $.rmAll(list); - $.add(list, nodes); - return ThreadWatcher.refreshIcon(); - }, - refresh: function() { - ThreadWatcher.build(); - g.threads.forEach(function(thread) { - var isWatched, j, len1, post, ref, toggler; - isWatched = ThreadWatcher.isWatched(thread); - if (thread.OP) { - ref = [thread.OP].concat(slice.call(thread.OP.clones)); - for (j = 0, len1 = ref.length; j < len1; j++) { - post = ref[j]; - if ((toggler = $('.watch-thread-link', post.nodes.info))) { - ThreadWatcher.setToggler(toggler, isWatched); - } - } - } - if (thread.catalogView) { - return thread.catalogView.nodes.root.classList.toggle('watched', isWatched); - } - }); - if (Conf['Pin Watched Threads']) { - return $.event('SortIndex', { - deferred: Conf['Index Mode'] !== 'catalog' - }); - } - }, - refreshIcon: function() { - var className, j, len1, ref; - ref = ['replies-unread', 'replies-quoting-you']; - for (j = 0, len1 = ref.length; j < len1; j++) { - className = ref[j]; - ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); - } - }, - update: function(siteID, boardID, threadID, newData) { - var data, j, key, len1, line, n, newLine, ref, ref1, val; - if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }) : void 0)) { - return; - } - if (newData.isDead && Conf['Auto Prune']) { - ThreadWatcher.rm(siteID, boardID, threadID); - return; - } - if (newData.isDead || newData.last === -1) { - ref1 = ['isArchived', 'page', 'lastPage', 'unread', 'quotingyou']; - for (j = 0, len1 = ref1.length; j < len1; j++) { - key = ref1[j]; - if (!(key in newData)) { - newData[key] = void 0; - } - } - } - if ((newData.last != null) && newData.last < data.last) { - newData.modified = void 0; - } - n = 0; - for (key in newData) { - val = newData[key]; - if (data[key] !== val) { - n++; - } - } - if (!n) { - return; - } - ThreadWatcher.db.extend({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - val: newData - }); - if ((line = $("#watched-threads > [data-site-i-d='" + siteID + "'][data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog))) { - newLine = ThreadWatcher.makeLine(siteID, boardID, threadID, data); - $.replace(line, newLine); - return ThreadWatcher.refreshIcon(); - } else { - return ThreadWatcher.refresh(); - } - }, - set404: function(boardID, threadID, cb) { - var data, ref; - if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ - boardID: boardID, - threadID: threadID - }) : void 0)) { - return cb(); - } - if (Conf['Auto Prune']) { - ThreadWatcher.db["delete"]({ - boardID: boardID, - threadID: threadID - }); - return cb(); - } - if (data.isDead && !((data.isArchived != null) || (data.page != null) || (data.lastPage != null) || (data.unread != null) || (data.quotingYou != null))) { - return cb(); - } - return ThreadWatcher.db.extend({ - boardID: boardID, - threadID: threadID, - val: { - isDead: true, - isArchived: void 0, - page: void 0, - lastPage: void 0, - unread: void 0, - quotingYou: void 0 - } - }, cb); - }, - toggle: function(thread) { - var boardID, siteID, threadID; - siteID = g.SITE.ID; - boardID = thread.board.ID; - threadID = thread.ID; - if (ThreadWatcher.db.get({ - boardID: boardID, - threadID: threadID - })) { - return ThreadWatcher.rm(siteID, boardID, threadID); - } else { - return ThreadWatcher.add(thread); - } - }, - add: function(thread, cb) { - var boardID, data, siteID, threadID; - data = {}; - siteID = g.SITE.ID; - boardID = thread.board.ID; - threadID = thread.ID; - if (thread.isDead) { - if (Conf['Auto Prune'] && ThreadWatcher.db.get({ - boardID: boardID, - threadID: threadID - })) { - ThreadWatcher.rm(siteID, boardID, threadID, cb); - return; - } - data.isDead = true; - } - if (thread.OP) { - data.excerpt = Get.threadExcerpt(thread); - } - return ThreadWatcher.addRaw(boardID, threadID, data, cb); - }, - addRaw: function(boardID, threadID, data, cb) { - var oldData, thread; - oldData = ThreadWatcher.db.get({ - boardID: boardID, - threadID: threadID, - defaultValue: $.dict() - }); - delete oldData.last; - delete oldData.modified; - $.extend(oldData, data); - ThreadWatcher.db.set({ - boardID: boardID, - threadID: threadID, - val: oldData - }, cb); - ThreadWatcher.refresh(); - thread = { - siteID: g.SITE.ID, - boardID: boardID, - threadID: threadID, - data: data, - force: true - }; - if (Conf['Show Page'] && !data.isDead) { - return ThreadWatcher.fetchBoard([thread]); - } else if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - return ThreadWatcher.fetchStatus(thread); - } - }, - rm: function(siteID, boardID, threadID, cb) { - ThreadWatcher.db["delete"]({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }, cb); - return ThreadWatcher.refresh(); - }, - menu: { - init: function() { - var menu; - if (!Conf['Thread Watcher']) { - return; - } - menu = this.menu = new UI.Menu('thread watcher'); - $.on($('.menu-button', ThreadWatcher.dialog), 'click', function(e) { - return menu.toggle(e, this, ThreadWatcher); - }); - return this.addMenuEntries(); - }, - addHeaderMenuEntry: function() { - var entryEl; - if (g.VIEW !== 'thread') { - return; - } - entryEl = $.el('a', { - href: 'javascript:;' - }); - Header.menu.addEntry({ - el: entryEl, - order: 60, - open: function() { - var addClass, ref, rmClass, text; - ref = !!ThreadWatcher.db.get({ - boardID: g.BOARD.ID, - threadID: g.THREADID - }) ? ['unwatch-thread', 'watch-thread', 'Unwatch thread'] : ['watch-thread', 'unwatch-thread', 'Watch thread'], addClass = ref[0], rmClass = ref[1], text = ref[2]; - $.addClass(entryEl, addClass); - $.rmClass(entryEl, rmClass); - entryEl.textContent = text; - return true; - } - }); - return $.on(entryEl, 'click', function() { - return ThreadWatcher.toggle(g.threads.get(g.BOARD + "." + g.THREADID)); - }); - }, - addMenuEntries: function() { - var cb, conf, entries, entry, j, len1, name, open, ref, ref1, text, title; - entries = []; - entries.push({ - text: 'Open all threads', - cb: ThreadWatcher.cb.openAll, - open: function() { - this.el.classList.toggle('disabled', !ThreadWatcher.list.firstElementChild); - return true; - } - }); - entries.push({ - text: 'Open unread threads', - cb: ThreadWatcher.cb.openUnread, - open: function() { - this.el.classList.toggle('disabled', !$('.replies-unread', ThreadWatcher.list)); - return true; - } - }); - entries.push({ - text: 'Open dead threads', - cb: ThreadWatcher.cb.openDeads, - open: function() { - this.el.classList.toggle('disabled', !$('.dead-thread', ThreadWatcher.list)); - return true; - } - }); - entries.push({ - text: 'Prune dead threads', - cb: ThreadWatcher.cb.pruneDeads, - open: function() { - this.el.classList.toggle('disabled', !$('.dead-thread', ThreadWatcher.list)); - return true; - } - }); - entries.push({ - text: 'Dismiss posts quoting you', - title: 'Unhighlight the thread watcher icon and threads until there are new replies quoting you.', - cb: ThreadWatcher.cb.dismiss, - open: function() { - this.el.classList.toggle('disabled', !$.hasClass(ThreadWatcher.shortcut, 'replies-quoting-you')); - return true; - } - }); - for (j = 0, len1 = entries.length; j < len1; j++) { - ref = entries[j], text = ref.text, title = ref.title, cb = ref.cb, open = ref.open; - entry = { - el: $.el('a', { - textContent: text, - href: 'javascript:;' - }) - }; - if (title) { - entry.el.title = title; - } - $.on(entry.el, 'click', cb); - entry.open = open.bind(entry); - this.menu.addEntry(entry); - } - ref1 = Config.threadWatcher; - for (name in ref1) { - conf = ref1[name]; - this.addCheckbox(name, conf[1]); - } - }, - addCheckbox: function(name, desc) { - var entry, input; - entry = { - type: 'thread watcher', - el: UI.checkbox(name, name.replace(' Thread Watcher', '')) - }; - entry.el.title = desc; - input = entry.el.firstElementChild; - if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { - input.disabled = true; - $.addClass(entry.el, 'disabled'); - entry.el.title += '\n[Remember Last Read Post is disabled.]'; - } - $.on(input, 'change', $.cb.checked); - if (name === 'Current Board' || name === 'Show Page' || name === 'Show Unread Count' || name === 'Show Site Prefix') { - $.on(input, 'change', ThreadWatcher.refresh); - } - if (name === 'Show Page' || name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') { - $.on(input, 'change', ThreadWatcher.fetchAuto); - } - return this.menu.addEntry(entry); - } - } - }; - - return ThreadWatcher; - -}).call(this); - -Unread = (function() { - var Unread; - - Unread = { - init: function() { - if (!(g.VIEW === 'thread' && (Conf['Unread Count'] || Conf['Unread Favicon'] || Conf['Unread Line'] || Conf['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { - return; - } - if (Conf['Remember Last Read Post']) { - $.sync('Remember Last Read Post', function(enabled) { - return Conf['Remember Last Read Post'] = enabled; - }); - this.db = new DataBoard('lastReadPosts', this.sync); - } - this.hr = $.el('hr', { - id: 'unread-line', - className: 'unread-line' - }); - this.posts = new Set(); - this.postsQuotingYou = new Set(); - this.order = new RandomAccessList(); - this.position = null; - Callbacks.Thread.push({ - name: 'Unread', - cb: this.node - }); - return Callbacks.Post.push({ - name: 'Unread', - cb: this.addPost - }); - }, - node: function() { - var ID, j, len, ref, ref1, resetLink; - Unread.thread = this; - Unread.title = d.title; - Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.ID - }) : void 0) || 0; - Unread.readCount = 0; - ref1 = this.posts.keys; - for (j = 0, len = ref1.length; j < len; j++) { - ID = ref1[j]; - if (+ID <= Unread.lastReadPost) { - Unread.readCount++; - } - } - $.one(d, '4chanXInitFinished', Unread.ready); - $.on(d, 'PostsInserted', Unread.onUpdate); - $.on(d, 'ThreadUpdate', function(e) { - if (e.detail[404]) { - return Unread.update(); - } - }); - resetLink = $.el('a', { - href: 'javascript:;', - className: 'unread-reset', - textContent: 'Mark all unread' - }); - $.on(resetLink, 'click', Unread.reset); - return Header.menu.addEntry({ - el: resetLink, - order: 70 - }); - }, - ready: function() { - if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { - Unread.scroll(); - } - Unread.setLine(true); - Unread.read(); - Unread.update(); - $.on(d, 'scroll visibilitychange', Unread.read); - if (Conf['Unread Line']) { - return $.on(d, 'visibilitychange', Unread.setLine); - } - }, - positionPrev: function() { - if (Unread.position) { - return Unread.position.prev; - } else { - return Unread.order.last; - } - }, - scroll: function() { - var bottom, hash, position; - if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { - return; - } - position = Unread.positionPrev(); - while (position) { - bottom = position.data.nodes.bottom; - if (!bottom.getBoundingClientRect().height) { - position = position.prev; - } else { - Header.scrollToIfNeeded(bottom, true); - break; - } - } - }, - reset: function() { - if (Unread.lastReadPost == null) { - return; - } - Unread.posts = new Set(); - Unread.postsQuotingYou = new Set(); - Unread.order = new RandomAccessList(); - Unread.position = null; - Unread.lastReadPost = 0; - Unread.readCount = 0; - Unread.thread.posts.forEach(function(post) { - return Unread.addPost.call(post); - }); - $.forceSync('Remember Last Read Post'); - if (Conf['Remember Last Read Post'] && (!Unread.thread.isDead || Unread.thread.isArchived)) { - Unread.db.set({ - boardID: Unread.thread.board.ID, - threadID: Unread.thread.ID, - val: 0 - }); - } - Unread.updatePosition(); - Unread.setLine(); - return Unread.update(); - }, - sync: function() { - var ID, i, j, lastReadPost, postIDs, ref, ref1; - if (Unread.lastReadPost == null) { - return; - } - lastReadPost = Unread.db.get({ - boardID: Unread.thread.board.ID, - threadID: Unread.thread.ID, - defaultValue: 0 - }); - if (!(Unread.lastReadPost < lastReadPost)) { - return; - } - Unread.lastReadPost = lastReadPost; - postIDs = Unread.thread.posts.keys; - for (i = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 1) { - ID = +postIDs[i]; - if (!Unread.thread.posts.get(ID).isFetchedQuote) { - if (ID > Unread.lastReadPost) { - break; - } - Unread.posts["delete"](ID); - Unread.postsQuotingYou["delete"](ID); - } - Unread.readCount++; - } - Unread.updatePosition(); - Unread.setLine(); - return Unread.update(); - }, - addPost: function() { - if (this.isFetchedQuote || this.isClone) { - return; - } - Unread.order.push(this); - if (this.ID <= Unread.lastReadPost || this.isHidden || QuoteYou.isYou(this)) { - return; - } - Unread.posts.add((Unread.posts.last = this.ID)); - Unread.addPostQuotingYou(this); - return Unread.position != null ? Unread.position : Unread.position = Unread.order[this.ID]; - }, - addPostQuotingYou: function(post) { - var j, len, quotelink, ref, ref1; - ref = post.nodes.quotelinks; - for (j = 0, len = ref.length; j < len; j++) { - quotelink = ref[j]; - if (!((ref1 = QuoteYou.db) != null ? ref1.get(Get.postDataFromLink(quotelink)) : void 0)) { - continue; - } - Unread.postsQuotingYou.add((Unread.postsQuotingYou.last = post.ID)); - Unread.openNotification(post); - return; - } - }, - openNotification: function(post, predicate) { - var notif; - if (predicate == null) { - predicate = ' replied to you'; - } - if (!Header.areNotificationsEnabled) { - return; - } - notif = new Notification("" + post.info.nameBlock + predicate, { - body: post.commentDisplay(), - icon: Favicon.logo - }); - notif.onclick = function() { - Header.scrollToIfNeeded(post.nodes.bottom, true); - return window.focus(); - }; - return notif.onshow = function() { - return setTimeout(function() { - return notif.close(); - }, 7 * $.SECOND); - }; - }, - onUpdate: function() { - return $.queueTask(function() { - Unread.setLine(); - Unread.read(); - return Unread.update(); - }); - }, - readSinglePost: function(post) { - var ID; - ID = post.ID; - if (!Unread.posts.has(ID)) { - return; - } - Unread.posts["delete"](ID); - Unread.postsQuotingYou["delete"](ID); - Unread.updatePosition(); - Unread.saveLastReadPost(); - return Unread.update(); - }, - read: $.debounce(100, function(e) { - var ID, bottom, count, data, ref; - if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { - Unread.saveLastReadPost(); - } - if (d.hidden || !Unread.posts.size) { - return; - } - count = 0; - while (Unread.position) { - ref = Unread.position, ID = ref.ID, data = ref.data; - bottom = data.nodes.bottom; - if (!(!bottom.getBoundingClientRect().height || Header.getBottomOf(bottom) > -1)) { - break; - } - count++; - Unread.posts["delete"](ID); - Unread.postsQuotingYou["delete"](ID); - Unread.position = Unread.position.next; - } - if (!count) { - return; - } - Unread.updatePosition(); - Unread.saveLastReadPost(); - if (e) { - return Unread.update(); - } - }), - updatePosition: function() { - while (Unread.position && !Unread.posts.has(Unread.position.ID)) { - Unread.position = Unread.position.next; - } - }, - saveLastReadPost: $.debounce(2 * $.SECOND, function() { - var ID, i, j, postIDs, ref, ref1; - $.forceSync('Remember Last Read Post'); - if (!(Conf['Remember Last Read Post'] && Unread.db)) { - return; - } - postIDs = Unread.thread.posts.keys; - for (i = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 1) { - ID = +postIDs[i]; - if (!Unread.thread.posts.get(ID).isFetchedQuote) { - if (Unread.posts.has(ID)) { - break; - } - Unread.lastReadPost = ID; - } - Unread.readCount++; - } - if (Unread.thread.isDead && !Unread.thread.isArchived) { - return; - } - return Unread.db.set({ - boardID: Unread.thread.board.ID, - threadID: Unread.thread.ID, - val: Unread.lastReadPost - }); - }), - setLine: function(force) { - var node, oldPosition, ref; - if (!Conf['Unread Line']) { - return; - } - if (Unread.hr.hidden || d.hidden || (force === true)) { - oldPosition = Unread.linePosition; - if ((Unread.linePosition = Unread.positionPrev())) { - if (Unread.linePosition !== oldPosition) { - node = Unread.linePosition.data.nodes.bottom; - if (((ref = node.nextSibling) != null ? ref.tagName : void 0) === 'BR') { - node = node.nextSibling; - } - $.after(node, Unread.hr); - } - } else { - $.rm(Unread.hr); - } - } - return Unread.hr.hidden = Unread.linePosition === Unread.order.last; - }, - update: function() { - var count, countQuotingYou, isDead, titleCount, titleDead, titleQuotingYou; - count = Unread.posts.size; - countQuotingYou = Unread.postsQuotingYou.size; - if (Conf['Unread Count']) { - titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : ''; - titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : ''; - titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title; - d.title = "" + titleQuotingYou + titleCount + titleDead; - } - Unread.saveThreadWatcherCount(); - if (Conf['Unread Favicon'] && g.SITE.software === 'yotsuba') { - isDead = Unread.thread.isDead; - return Favicon.set((countQuotingYou ? (isDead ? 'unreadDeadY' : 'unreadY') : count ? (isDead ? 'unreadDead' : 'unread') : (isDead ? 'dead' : 'default'))); - } - }, - saveThreadWatcherCount: $.debounce(2 * $.SECOND, function() { - var i, j, posts, quotingYou, ref; - $.forceSync('Remember Last Read Post'); - if (Conf['Remember Last Read Post'] && (!Unread.thread.isDead || Unread.thread.isArchived)) { - quotingYou = !Conf['Require OP Quote Link'] && QuoteYou.isYou(Unread.thread.OP) ? Unread.posts : Unread.postsQuotingYou; - if (!quotingYou.size) { - quotingYou.last = 0; - } else if (!quotingYou.has(quotingYou.last)) { - quotingYou.last = 0; - posts = Unread.thread.posts.keys; - for (i = j = ref = posts.length - 1; j >= 0; i = j += -1) { - if (quotingYou.has(+posts[i])) { - quotingYou.last = posts[i]; - break; - } - } - } - return ThreadWatcher.update(g.SITE.ID, Unread.thread.board.ID, Unread.thread.ID, { - last: Unread.thread.lastPost, - isDead: Unread.thread.isDead, - isArchived: Unread.thread.isArchived, - unread: Unread.posts.size, - quotingYou: quotingYou.last || 0 - }); - } - }) - }; - - return Unread; - -}).call(this); - -UnreadIndex = (function() { - var UnreadIndex; - - UnreadIndex = { - lastReadPost: $.dict(), - hr: $.dict(), - markReadLink: $.dict(), - init: function() { - if (!(g.VIEW === 'index' && Conf['Remember Last Read Post'] && Conf['Unread Line in Index'])) { - return; - } - this.enabled = true; - this.db = new DataBoard('lastReadPosts', this.sync); - Callbacks.Thread.push({ - name: 'Unread Line in Index', - cb: this.node - }); - $.on(d, 'IndexRefreshInternal', this.onIndexRefresh); - return $.on(d, 'PostsInserted PostsRemoved', this.onPostsInserted); - }, - node: function() { - UnreadIndex.lastReadPost[this.fullID] = UnreadIndex.db.get({ - boardID: this.board.ID, - threadID: this.ID - }) || 0; - if (!Index.enabled) { - return UnreadIndex.update(this); - } - }, - onIndexRefresh: function(e) { - var i, len, ref, results, thread, threadID; - if (e.detail.isCatalog) { - return; - } - ref = e.detail.threadIDs; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - threadID = ref[i]; - thread = g.threads.get(threadID); - results.push(UnreadIndex.update(thread)); - } - return results; - }, - onPostsInserted: function(e) { - var ref, ref1, thread, wasVisible; - if (e.target === Index.root) { - return; - } - thread = Get.threadFromNode(e.target); - if (!thread || thread.nodes.root !== e.target) { - return; - } - wasVisible = !!((ref = UnreadIndex.hr[thread.fullID]) != null ? ref.parentNode : void 0); - UnreadIndex.update(thread); - if (Conf['Scroll to Last Read Post'] && e.type === 'PostsInserted' && !wasVisible && !!((ref1 = UnreadIndex.hr[thread.fullID]) != null ? ref1.parentNode : void 0)) { - return Header.scrollToIfNeeded(UnreadIndex.hr[thread.fullID], true); - } - }, - sync: function() { - return g.threads.forEach(function(thread) { - var lastReadPost, ref; - lastReadPost = UnreadIndex.db.get({ - boardID: thread.board.ID, - threadID: thread.ID - }) || 0; - if (lastReadPost !== UnreadIndex.lastReadPost[thread.fullID]) { - UnreadIndex.lastReadPost[thread.fullID] = lastReadPost; - if ((ref = thread.nodes.root) != null ? ref.parentNode : void 0) { - return UnreadIndex.update(thread); - } - } - }); - }, - update: function(thread) { - var divider, firstUnread, hasUnread, hr, lastReadPost, link, repliesRead, repliesShown; - lastReadPost = UnreadIndex.lastReadPost[thread.fullID]; - repliesShown = 0; - repliesRead = 0; - firstUnread = null; - thread.posts.forEach(function(post) { - if (post.isReply && thread.nodes.root.contains(post.nodes.root)) { - repliesShown++; - if (post.ID <= lastReadPost) { - return repliesRead++; - } else if ((!firstUnread || post.ID < firstUnread.ID) && !post.isHidden && !QuoteYou.isYou(post)) { - return firstUnread = post; - } - } - }); - hr = UnreadIndex.hr[thread.fullID]; - if (firstUnread && (repliesRead || (lastReadPost === thread.OP.ID && (!$(g.SITE.selectors.summary, thread.nodes.root) || thread.ID in ExpandThread.statuses)))) { - if (!hr) { - hr = UnreadIndex.hr[thread.fullID] = $.el('hr', { - className: 'unread-line' - }); - } - $.before(firstUnread.nodes.root, hr); - } else { - $.rm(hr); - } - hasUnread = repliesShown ? firstUnread || !repliesRead : Index.enabled ? thread.lastPost > lastReadPost : thread.OP.ID > lastReadPost; - thread.nodes.root.classList.toggle('unread-thread', hasUnread); - link = UnreadIndex.markReadLink[thread.fullID]; - if (!link) { - link = UnreadIndex.markReadLink[thread.fullID] = $.el('a', { - className: 'unread-mark-read brackets-wrap', - href: 'javascript:;', - textContent: 'Mark Read' - }); - $.on(link, 'click', UnreadIndex.markRead); - } - if ((divider = $(g.SITE.selectors.threadDivider, thread.nodes.root))) { - return $.before(divider, link); - } else { - return $.add(thread.nodes.root, link); - } - }, - markRead: function() { - var thread; - thread = Get.threadFromNode(this); - UnreadIndex.lastReadPost[thread.fullID] = thread.lastPost; - UnreadIndex.db.set({ - boardID: thread.board.ID, - threadID: thread.ID, - val: thread.lastPost - }); - $.rm(UnreadIndex.hr[thread.fullID]); - thread.nodes.root.classList.remove('unread-thread'); - return ThreadWatcher.update(g.SITE.ID, thread.board.ID, thread.ID, { - last: thread.lastPost, - unread: 0, - quotingYou: 0 - }); - } - }; - - return UnreadIndex; - -}).call(this); - -Captcha = {}; - -(function() { - Captcha.cache = { - init: function() { - $.on(d, 'SaveCaptcha', (function(_this) { - return function(e) { - return _this.saveAPI(e.detail); - }; - })(this)); - return $.on(d, 'NoCaptcha', (function(_this) { - return function(e) { - return _this.noCaptcha(e.detail); - }; - })(this)); - }, - captchas: [], - getCount: function() { - return this.captchas.length; - }, - neededRaw: function() { - return !(this.haveCookie() || this.captchas.length || QR.req || this.submitCB) && (QR.posts.length > 1 || Conf['Auto-load captcha'] || !QR.posts[0].isOnlyQuotes() || QR.posts[0].file); - }, - needed: function() { - return this.neededRaw() && $.event('LoadCaptcha'); - }, - prerequest: function() { - if (!Conf['Prerequest Captcha']) { - return; - } - return $.queueTask((function(_this) { - return function() { - var isReply; - if (!_this.prerequested && _this.neededRaw() && !$.event('LoadCaptcha') && !QR.captcha.occupied() && QR.cooldown.seconds <= 60 && QR.selected === QR.posts[QR.posts.length - 1] && !QR.selected.isOnlyQuotes()) { - isReply = QR.selected.thread !== 'new'; - if (!$.event('RequestCaptcha', { - isReply: isReply - })) { - _this.prerequested = true; - _this.submitCB = function(captcha) { - if (captcha) { - return _this.save(captcha); - } - }; - return _this.updateCount(); - } - } - }; - })(this)); - }, - haveCookie: function() { - return /\b_ct=/.test(d.cookie) && QR.posts[0].thread !== 'new'; - }, - getOne: function() { - var captcha; - delete this.prerequested; - this.clear(); - if ((captcha = this.captchas.shift())) { - this.count(); - return captcha; - } else { - return null; - } - }, - request: function(isReply) { - if (!this.submitCB) { - if ($.event('RequestCaptcha', { - isReply: isReply - })) { - return; - } - } - return (function(_this) { - return function(cb) { - _this.submitCB = cb; - return _this.updateCount(); - }; - })(this); - }, - abort: function() { - if (this.submitCB) { - delete this.submitCB; - $.event('AbortCaptcha'); - return this.updateCount(); - } - }, - saveAPI: function(captcha) { - var cb; - if ((cb = this.submitCB)) { - delete this.submitCB; - cb(captcha); - return this.updateCount(); - } else { - return this.save(captcha); - } - }, - noCaptcha: function(detail) { - var cb; - if ((cb = this.submitCB)) { - if (!this.haveCookie() || (detail != null ? detail.error : void 0)) { - QR.error((detail != null ? detail.error : void 0) || 'Failed to retrieve captcha.'); - QR.captcha.setup(d.activeElement === QR.nodes.status); - } - delete this.submitCB; - cb(); - return this.updateCount(); - } - }, - save: function(captcha) { - var cb; - if ((cb = this.submitCB)) { - this.abort(); - cb(captcha); - return; - } - this.captchas.push(captcha); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - return this.count(); - }, - clear: function() { - var captcha, i, j, len, now, ref; - if (this.captchas.length) { - now = Date.now(); - ref = this.captchas; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - captcha = ref[i]; - if (captcha.timeout > now) { - break; - } - } - if (i) { - this.captchas = this.captchas.slice(i); - return this.count(); - } - } - }, - count: function() { - clearTimeout(this.timer); - if (this.captchas.length) { - this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); - } - return this.updateCount(); - }, - updateCount: function() { - return $.event('CaptchaCount', this.captchas.length); - } - }; - -}).call(this); - -(function() { - Captcha.replace = { - init: function() { - var ref; - if (!(g.SITE.software === 'yotsuba' && d.cookie.indexOf('pass_enabled=1') < 0)) { - return; - } - if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { - $.ready(Captcha.replace.noscript); - return; - } - if (Conf['captchaLanguage'].trim()) { - if ((ref = location.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') { - return $.onExists(doc, '#captchaFormPart', function(node) { - return $.onExists(node, 'iframe[src^="https://www.google.com/recaptcha/"]', Captcha.replace.iframe); - }); - } else { - return $.onExists(doc, 'iframe[src^="https://www.google.com/recaptcha/"]', Captcha.replace.iframe); - } - } - }, - noscript: function() { - var insert, noscript, original, span, toggle; - if (!((original = $('#g-recaptcha')) && (noscript = $('noscript', original.parentNode)))) { - return; - } - span = $.el('span', { - id: 'captcha-forced-noscript' - }); - $.replace(noscript, span); - $.rm(original); - insert = function() { - span.innerHTML = noscript.textContent; - return Captcha.replace.iframe($('iframe[src^="https://www.google.com/recaptcha/"]', span)); - }; - if ((toggle = $('#togglePostFormLink a, #form-link'))) { - return $.on(toggle, 'click', insert); - } else { - return insert(); - } - }, - iframe: function(iframe) { - var lang, src; - if ((lang = Conf['captchaLanguage'].trim())) { - src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); - if (iframe.src !== src) { - iframe.src = src; - } - } - } - }; - -}).call(this); - -(function() { - Captcha.t = { - init: function() { - var root; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#t-root') || !$.id('postForm'))) { - return; - } - root = $.el('div', { - className: 'captcha-root' - }); - this.nodes = { - root: root - }; - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-t'); - return $.after(QR.nodes.com.parentNode, root); - }, - moreNeeded: function() {}, - getThread: function() { - var boardID, threadID; - boardID = g.BOARD.ID; - if (QR.posts[0].thread === 'new') { - threadID = '0'; - } else { - threadID = '' + QR.posts[0].thread; - } - return { - boardID: boardID, - threadID: threadID - }; - }, - setup: function(focus) { - if (!this.isEnabled) { - return; - } - if (!this.nodes.container) { - this.nodes.container = $.el('div', { - className: 'captcha-container' - }); - $.prepend(this.nodes.root, this.nodes.container); - Captcha.t.currentThread = Captcha.t.getThread(); - $.global(function() { - var el; - el = document.querySelector('#qr .captcha-container'); - window.TCaptcha.init(el, this.boardID, +this.threadID); - return window.TCaptcha.setErrorCb(function(err) { - return window.dispatchEvent(new CustomEvent('CreateNotification', { - detail: { - type: 'warning', - content: '' + err - } - })); - }); - }, Captcha.t.currentThread); - } - if (focus) { - return $('#t-resp').focus(); - } - }, - destroy: function() { - if (!(this.isEnabled && this.nodes.container)) { - return; - } - $.global(function() { - return window.TCaptcha.destroy(); - }); - $.rm(this.nodes.container); - return delete this.nodes.container; - }, - updateThread: function() { - var boardID, newThread, ref, threadID; - if (!this.isEnabled) { - return; - } - ref = Captcha.t.currentThread || {}, boardID = ref.boardID, threadID = ref.threadID; - newThread = Captcha.t.getThread(); - if (!(newThread.boardID === boardID && newThread.threadID === threadID)) { - Captcha.t.destroy(); - return Captcha.t.setup(); - } - }, - getOne: function() { - var el, i, key, len, ref, response; - response = {}; - if (this.nodes.container) { - ref = ['t-response', 't-challenge']; - for (i = 0, len = ref.length; i < len; i++) { - key = ref[i]; - response[key] = $("[name='" + key + "']", this.nodes.container).value; - } - } - if (!response['t-response'] && !((el = $('#t-msg')) && /Verification not required/i.test(el.textContent))) { - response = null; - } - return response; - }, - setUsed: function() { - if (!this.isEnabled) { - return; - } - if (this.nodes.container) { - return $.global(function() { - return window.TCaptcha.clearChallenge(); - }); - } - }, - occupied: function() { - return !!this.nodes.container; - } - }; - -}).call(this); - -(function() { - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Captcha.v2 = { - lifetime: 2 * $.MINUTE, - init: function() { - var counter, root; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captcha-forced-noscript') || !$.id('postForm'))) { - return; - } - if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { - $.addClass(QR.nodes.el, 'noscript-captcha'); - } - Captcha.cache.init(); - $.on(d, 'CaptchaCount', this.count.bind(this)); - root = $.el('div', { - className: 'captcha-root' - }); - $.extend(root, {innerHTML: "
    "}); - counter = $('.captcha-counter > a', root); - this.nodes = { - root: root, - counter: counter - }; - this.count(); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); - $.after(QR.nodes.com.parentNode, root); - $.on(counter, 'click', this.toggle.bind(this)); - $.on(counter, 'keydown', (function(_this) { - return function(e) { - if (Keybinds.keyCode(e) !== 'Space') { - return; - } - _this.toggle(); - e.preventDefault(); - return e.stopPropagation(); - }; - })(this)); - return $.on(window, 'captcha:success', (function(_this) { - return function() { - return $.queueTask(function() { - return _this.save(false); - }); - }; - })(this)); - }, - timeouts: {}, - prevNeeded: 0, - noscriptURL: function() { - var lang, url; - url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; - if ((lang = Conf['captchaLanguage'].trim())) { - url += "&hl=" + (encodeURIComponent(lang)); - } - return url; - }, - moreNeeded: function() { - return $.queueTask((function(_this) { - return function() { - var needed; - needed = Captcha.cache.needed(); - if (needed && !_this.prevNeeded) { - _this.setup(QR.cooldown.auto && d.activeElement === QR.nodes.status); - } - return _this.prevNeeded = needed; - }; - })(this)); - }, - toggle: function() { - if (this.nodes.container && !this.timeouts.destroy) { - return this.destroy(); - } else { - return this.setup(true, true); - } - }, - setup: function(focus, force) { - if (!(this.isEnabled && (Captcha.cache.needed() || force))) { - return; - } - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - this.nodes.counter.focus(); - } - if (this.timeouts.destroy) { - clearTimeout(this.timeouts.destroy); - delete this.timeouts.destroy; - return this.reload(); - } - if (this.nodes.container) { - $.queueTask((function(_this) { - return function() { - var iframe; - if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe[src^="https://www.google.com/recaptcha/"]', _this.nodes.container))) { - iframe.focus(); - return QR.focus(); - } - }; - })(this)); - return; - } - this.nodes.container = $.el('div', { - className: 'captcha-container' - }); - $.prepend(this.nodes.root, this.nodes.container); - new MutationObserver(this.afterSetup.bind(this)).observe(this.nodes.container, { - childList: true, - subtree: true - }); - if (this.noscript) { - return this.setupNoscript(); - } else { - return this.setupJS(); - } - }, - setupNoscript: function() { - var div, iframe, textarea; - iframe = $.el('iframe', { - id: 'qr-captcha-iframe', - scrolling: 'no', - src: this.noscriptURL() - }); - div = $.el('div'); - textarea = $.el('textarea'); - $.add(div, textarea); - return $.add(this.nodes.container, [iframe, div]); - }, - setupJS: function() { - return $.global(function() { - var cbNative, render, script; - render = function() { - var classList, container; - classList = document.documentElement.classList; - container = document.querySelector('#qr .captcha-container'); - return container.dataset.widgetID = window.grecaptcha.render(container, { - sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', - theme: classList.contains('tomorrow') || classList.contains('spooky') || classList.contains('dark-captcha') ? 'dark' : 'light', - callback: function(response) { - return window.dispatchEvent(new CustomEvent('captcha:success', { - detail: response - })); - } - }); - }; - if (window.grecaptcha) { - return render(); - } else { - cbNative = window.onRecaptchaLoaded; - window.onRecaptchaLoaded = function() { - render(); - return cbNative(); - }; - if (!document.head.querySelector('script[src^="https://www.google.com/recaptcha/api.js"]')) { - script = document.createElement('script'); - script.src = 'https://www.google.com/recaptcha/api.js?onload=onRecaptchaLoaded&render=explicit'; - return document.head.appendChild(script); - } - } - }); - }, - afterSetup: function(mutations) { - var i, iframe, j, len, len1, mutation, node, ref, textarea; - for (i = 0, len = mutations.length; i < len; i++) { - mutation = mutations[i]; - ref = mutation.addedNodes; - for (j = 0, len1 = ref.length; j < len1; j++) { - node = ref[j]; - if ((iframe = $.x('./descendant-or-self::iframe[starts-with(@src, "https://www.google.com/recaptcha/")]', node))) { - this.setupIFrame(iframe); - } - if ((textarea = $.x('./descendant-or-self::textarea', node))) { - this.setupTextArea(textarea); - } - } - } - }, - setupIFrame: function(iframe) { - var ref, ref1; - if (!doc.contains(iframe)) { - return; - } - Captcha.replace.iframe(iframe); - $.addClass(QR.nodes.el, 'captcha-open'); - this.fixQRPosition(); - $.on(iframe, 'load', this.fixQRPosition); - if (d.activeElement === this.nodes.counter) { - iframe.focus(); - } - if (((ref = $.engine) === 'blink' || ref === 'edge') && (ref1 = iframe.parentNode, indexOf.call($$('#qr .captcha-container > div > div:first-of-type'), ref1) >= 0)) { - return $.on(iframe.parentNode, 'scroll', function() { - return this.scrollTop = 0; - }); - } - }, - fixQRPosition: function() { - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = ''; - return QR.nodes.el.style.bottom = '0px'; - } - }, - setupTextArea: function(textarea) { - return $.one(textarea, 'input', (function(_this) { - return function() { - return _this.save(true); - }; - })(this)); - }, - destroy: function() { - if (!this.isEnabled) { - return; - } - delete this.timeouts.destroy; - $.rmClass(QR.nodes.el, 'captcha-open'); - if (this.nodes.container) { - $.global(function() { - var container; - container = document.querySelector('#qr .captcha-container'); - return window.grecaptcha.reset(container.dataset.widgetID); - }); - $.rm(this.nodes.container); - return delete this.nodes.container; - } - }, - getOne: function(isReply) { - return Captcha.cache.getOne(isReply); - }, - save: function(pasted, token) { - var base, focus, ref; - Captcha.cache.save({ - response: token || $('textarea', this.nodes.container).value, - timeout: Date.now() + this.lifetime - }); - focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); - if (Captcha.cache.needed()) { - if (focus) { - if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { - this.nodes.counter.focus(); - } else { - QR.nodes.status.focus(); - } - } - this.reload(); - } else { - if (pasted) { - this.destroy(); - } else { - if ((base = this.timeouts).destroy == null) { - base.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND); - } - } - if (focus) { - QR.nodes.status.focus(); - } - } - if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { - return QR.submit(); - } - }, - count: function() { - var count, loading; - count = Captcha.cache.getCount(); - loading = Captcha.cache.submitCB ? '...' : ''; - this.nodes.counter.textContent = "Captchas: " + count + loading; - return this.moreNeeded(); - }, - reload: function() { - if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { - this.destroy(); - return this.setup(false, true); - } else { - return $.global(function() { - var container; - container = document.querySelector('#qr .captcha-container'); - return window.grecaptcha.reset(container.dataset.widgetID); - }); - } - }, - occupied: function() { - return !!this.nodes.container && !this.timeouts.destroy; - } - }; - -}).call(this); - -PassLink = (function() { - var PassLink; - - PassLink = { - init: function() { - if (!(g.SITE.software === 'yotsuba' && Conf['Pass Link'])) { - return; - } - return Main.ready(this.ready); - }, - ready: function() { - var passLink, styleSelector; - if (!(styleSelector = $.id('styleSelector'))) { - return; - } - passLink = $.el('span', { - className: 'brackets-wrap pass-link-container' - }); - $.extend(passLink, {innerHTML: "4chan Pass"}); - $.on(passLink.firstElementChild, 'click', function() { - return window.open("//sys." + (location.hostname.split('.')[1]) + ".org/auth", Date.now(), 'width=500,height=280,toolbar=0'); - }); - return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); - } - }; - - return PassLink; - -}).call(this); - -PostRedirect = (function() { - var PostRedirect; - - PostRedirect = { - init: function() { - return $.on(d, 'QRPostSuccessful', (function(_this) { - return function(e) { - if (!e.detail.redirect) { - return; - } - _this.event = e; - _this.delays = 0; - return $.queueTask(function() { - if (e === _this.event && _this.delays === 0) { - return location.href = e.detail.redirect; - } - }); - }; - })(this)); - }, - delays: 0, - delay: function() { - var e; - if (!this.event) { - return null; - } - e = this.event; - this.delays++; - return (function(_this) { - return function() { - if (e !== _this.event) { - return; - } - _this.delays--; - if (_this.delays === 0) { - return location.href = e.detail.redirect; - } - }; - })(this); - } - }; - - return PostRedirect; - -}).call(this); - -PostSuccessful = (function() { - var PostSuccessful; - - PostSuccessful = { - init: function() { - if (!Conf['Remember Your Posts']) { - return; - } - return $.ready(this.ready); - }, - ready: function() { - var _, db, postID, ref, threadID; - if (d.title !== 'Post successful!') { - return; - } - ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; - postID = +postID; - threadID = +threadID || postID; - db = new DataBoard('yourPosts'); - return db.set({ - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID, - val: true - }); - } - }; - - return PostSuccessful; - -}).call(this); - -QR = (function() { - var QR, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - QR = { - mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], - validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, - typeFromExtension: { - 'jpg': 'image/jpeg', - 'jpeg': 'image/jpeg', - 'png': 'image/png', - 'gif': 'image/gif', - 'pdf': 'application/pdf', - 'swf': 'application/vnd.adobe.flash.movie', - 'webm': 'video/webm' - }, - extensionFromType: { - 'image/jpeg': 'jpg', - 'image/png': 'png', - 'image/gif': 'gif', - 'application/pdf': 'pdf', - 'application/vnd.adobe.flash.movie': 'swf', - 'application/x-shockwave-flash': 'swf', - 'video/webm': 'webm' - }, - init: function() { - var sc; - if (!Conf['Quick Reply']) { - return; - } - this.posts = []; - $.on(d, '4chanXInitFinished', function() { - return BoardConfig.ready(QR.initReady); - }); - Callbacks.Post.push({ - name: 'Quick Reply', - cb: this.node - }); - this.shortcut = sc = $.el('a', { - className: 'fa fa-comment-o disabled', - textContent: 'QR', - title: 'Quick Reply', - href: 'javascript:;' - }); - $.on(sc, 'click', function() { - if (!QR.postingIsEnabled) { - return; - } - if (Conf['Persistent QR'] || !QR.nodes || QR.nodes.el.hidden) { - QR.open(); - return QR.nodes.com.focus(); - } else { - return QR.close(); - } - }); - return Header.addShortcut('qr', sc, 540); - }, - initReady: function() { - var captchaVersion, config, link, linkBot, navLinksBot, origToggle, prop; - captchaVersion = $('#g-recaptcha, #captcha-forced-noscript') ? 'v2' : 't'; - QR.captcha = Captcha[captchaVersion]; - QR.postingIsEnabled = true; - config = g.BOARD.config; - prop = function(key, def) { - var ref; - return +((ref = config[key]) != null ? ref : def); - }; - QR.min_width = prop('min_image_width', 1); - QR.min_height = prop('min_image_height', 1); - QR.max_width = QR.max_height = 10000; - QR.max_size = prop('max_filesize', 4194304); - QR.max_size_video = prop('max_webm_filesize', QR.max_size); - QR.max_comment = prop('max_comment_chars', 2000); - QR.max_width_video = QR.max_height_video = 2048; - QR.max_duration_video = prop('max_webm_duration', 120); - QR.forcedAnon = !!config.forced_anon; - QR.spoiler = !!config.spoilers; - if ((origToggle = $.id('togglePostFormLink'))) { - link = $.el('h1', { - className: "qr-link-container" - }); - $.extend(link, {innerHTML: "" + ((g.VIEW === "thread") ? "Reply to Thread" : "Start a Thread") + ""}); - QR.link = link.firstElementChild; - $.on(link.firstChild, 'click', function() { - QR.open(); - return QR.nodes.com.focus(); - }); - $.before(origToggle, link); - origToggle.firstElementChild.textContent = 'Original Form'; - } - if (g.VIEW === 'thread') { - linkBot = $.el('div', { - className: "brackets-wrap qr-link-container-bottom" - }); - $.extend(linkBot, {innerHTML: "Reply to Thread"}); - $.on(linkBot.firstElementChild, 'click', function() { - QR.open(); - return QR.nodes.com.focus(); - }); - if ((navLinksBot = $('.navLinksBot'))) { - $.prepend(navLinksBot, linkBot); - } - } - $.on(d, 'QRGetFile', QR.getFile); - $.on(d, 'QRDrawFile', QR.drawFile); - $.on(d, 'QRSetFile', QR.setFile); - $.on(d, 'paste', QR.paste); - $.on(d, 'dragover', QR.dragOver); - $.on(d, 'drop', QR.dropFile); - $.on(d, 'dragstart dragend', QR.drag); - $.on(d, 'IndexRefreshInternal', QR.generatePostableThreadsList); - $.on(d, 'ThreadUpdate', QR.statusCheck); - if (!Conf['Persistent QR']) { - return; - } - QR.open(); - if (Conf['Auto Hide QR']) { - return QR.hide(); - } - }, - statusCheck: function() { - var thread; - if (!QR.nodes) { - return; - } - thread = QR.posts[0].thread; - if (thread !== 'new' && g.threads.get(g.BOARD + "." + thread).isDead) { - return QR.abort(); - } else { - return QR.status(); - } - }, - node: function() { - $.on(this.nodes.quote, 'click', QR.quote); - if (this.isFetchedQuote) { - return QR.generatePostableThreadsList(); - } - }, - open: function() { - var err; - if (QR.nodes) { - if (QR.nodes.el.hidden) { - QR.captcha.setup(); - } - QR.nodes.el.hidden = false; - QR.unhide(); - } else { - try { - QR.dialog(); - } catch (error) { - err = error; - delete QR.nodes; - Main.handleErrors({ - message: 'Quick Reply dialog creation crashed.', - error: err - }); - return; - } - } - return $.rmClass(QR.shortcut, 'disabled'); - }, - close: function() { - var j, len, post, ref; - if (QR.req) { - QR.abort(); - return; - } - QR.nodes.el.hidden = true; - QR.cleanNotifications(); - QR.blur(); - $.rmClass(QR.nodes.el, 'dump'); - $.addClass(QR.shortcut, 'disabled'); - new QR.post(true); - ref = QR.posts.splice(0, QR.posts.length - 1); - for (j = 0, len = ref.length; j < len; j++) { - post = ref[j]; - post["delete"](); - } - QR.cooldown.auto = false; - QR.status(); - return QR.captcha.destroy(); - }, - focus: function() { - return $.queueTask(function() { - if (!QR.inBubble()) { - QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); - return QR.nodes.el.classList.toggle('focus', QR.hasFocus); - } - }); - }, - inBubble: function() { - var bubbles, ref; - bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { - return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; - }); - }, - hide: function() { - QR.blur(); - $.addClass(QR.nodes.el, 'autohide'); - return QR.nodes.autohide.checked = true; - }, - unhide: function() { - $.rmClass(QR.nodes.el, 'autohide'); - return QR.nodes.autohide.checked = false; - }, - toggleHide: function() { - if (this.checked) { - return QR.hide(); - } else { - return QR.unhide(); - } - }, - blur: function() { - if (QR.nodes.el.contains(d.activeElement)) { - return d.activeElement.blur(); - } - }, - toggleSJIS: function(e) { - e.preventDefault(); - Conf['sjisPreview'] = !Conf['sjisPreview']; - $.set('sjisPreview', Conf['sjisPreview']); - return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); - }, - texPreviewShow: function() { - if ($.hasClass(QR.nodes.el, 'tex-preview')) { - return QR.texPreviewHide(); - } - $.addClass(QR.nodes.el, 'tex-preview'); - QR.nodes.texPreview.textContent = QR.nodes.com.value; - return $.event('mathjax', null, QR.nodes.texPreview); - }, - texPreviewHide: function() { - return $.rmClass(QR.nodes.el, 'tex-preview'); - }, - addPost: function() { - var wasOpen; - wasOpen = QR.nodes && !QR.nodes.el.hidden; - QR.open(); - if (wasOpen) { - $.addClass(QR.nodes.el, 'dump'); - new QR.post(true); - } - return QR.nodes.com.focus(); - }, - setCustomCooldown: function(enabled) { - Conf['customCooldownEnabled'] = enabled; - QR.cooldown.customCooldown = enabled; - return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); - }, - toggleCustomCooldown: function() { - var enabled; - enabled = $.hasClass(QR.nodes.customCooldown, 'disabled'); - QR.setCustomCooldown(enabled); - return $.set('customCooldownEnabled', enabled); - }, - error: function(err, focusOverride) { - var el, notice, notif; - QR.open(); - if (typeof err === 'string') { - el = $.tn(err); - } else { - el = err; - el.removeAttribute('style'); - } - notice = new Notice('warning', el); - QR.notifications.push(notice); - if (!Header.areNotificationsEnabled) { - if (d.hidden && !QR.cooldown.auto) { - return alert(el.textContent); - } - } else if (d.hidden || !(focusOverride || d.hasFocus())) { - notif = new Notification(el.textContent, { - body: el.textContent, - icon: Favicon.logo - }); - notif.onclick = function() { - return window.focus(); - }; - if ($.engine !== 'gecko') { - notif.onclose = function() { - return notice.close(); - }; - return notif.onshow = function() { - return setTimeout(function() { - notif.onclose = null; - return notif.close(); - }, 7 * $.SECOND); - }; - } - } - }, - connectionError: function() { - return $.el('span', {innerHTML: "Connection error while posting. [More info]"}); - }, - notifications: [], - cleanNotifications: function() { - var j, len, notification, ref; - ref = QR.notifications; - for (j = 0, len = ref.length; j < len; j++) { - notification = ref[j]; - notification.close(); - } - return QR.notifications = []; - }, - status: function() { - var disabled, status, thread, value; - if (!QR.nodes) { - return; - } - thread = QR.posts[0].thread; - if (thread !== 'new' && g.threads.get(g.BOARD + "." + thread).isDead) { - value = 'Dead'; - disabled = true; - QR.cooldown.auto = false; - } - value = QR.req ? QR.req.progress : QR.cooldown.seconds || value; - status = QR.nodes.status; - status.value = !value ? 'Submit' : QR.cooldown.auto ? "Auto " + value : value; - return status.disabled = disabled || false; - }, - openPost: function() { - var index; - QR.open(); - if (QR.selected.isLocked) { - index = QR.posts.indexOf(QR.selected); - (QR.posts[index + 1] || new QR.post()).select(); - $.addClass(QR.nodes.el, 'dump'); - return QR.cooldown.auto = true; - } - }, - quote: function(e) { - var ancestor, base, caretPos, com, frag, i, insideCode, j, k, l, len, len1, len2, len3, n, node, o, post, postRange, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, root, sel, text, thread, wasOnlyQuotes; - if (e != null) { - e.preventDefault(); - } - if (!QR.postingIsEnabled) { - return; - } - sel = d.getSelection(); - post = Get.postFromNode(this); - root = post.nodes.root; - postRange = new Range(); - postRange.selectNode(root); - text = post.board.ID === g.BOARD.ID ? ">>" + post + "\n" : ">>>/" + post.board + "/" + post + "\n"; - for (i = j = 0, ref = sel.rangeCount; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { - try { - range = sel.getRangeAt(i); - if (range.compareBoundaryPoints(Range.START_TO_START, postRange) < 0) { - range.setStartBefore(root); - } - if (range.compareBoundaryPoints(Range.END_TO_END, postRange) > 0) { - range.setEndAfter(root); - } - if (!range.toString().trim()) { - continue; - } - frag = range.cloneContents(); - ancestor = range.commonAncestorContainer; - if ($.x('ancestor-or-self::*[self::s or contains(@class,"removed-spoiler")]', ancestor)) { - $.prepend(frag, $.tn('[spoiler]')); - $.add(frag, $.tn('[/spoiler]')); - } - if (insideCode = $.x('ancestor-or-self::pre[contains(@class,"prettyprint")]', ancestor)) { - $.prepend(frag, $.tn('[code]')); - $.add(frag, $.tn('[/code]')); - } - ref1 = $$((insideCode ? 'br' : '.prettyprint br'), frag); - for (k = 0, len = ref1.length; k < len; k++) { - node = ref1[k]; - $.replace(node, $.tn('\n')); - } - ref2 = $$('br', frag); - for (l = 0, len1 = ref2.length; l < len1; l++) { - node = ref2[l]; - if (node !== frag.lastChild) { - $.replace(node, $.tn('\n>')); - } - } - if (typeof (base = g.SITE).insertTags === "function") { - base.insertTags(frag); - } - ref3 = $$('.linkify[data-original]', frag); - for (n = 0, len2 = ref3.length; n < len2; n++) { - node = ref3[n]; - $.replace(node, $.tn(node.dataset.original)); - } - ref4 = $$('.embedder', frag); - for (o = 0, len3 = ref4.length; o < len3; o++) { - node = ref4[o]; - if (((ref5 = node.previousSibling) != null ? ref5.nodeValue : void 0) === ' ') { - $.rm(node.previousSibling); - } - $.rm(node); - } - text += ">" + (frag.textContent.trim()) + "\n"; - } catch (error) {} - } - QR.openPost(); - ref6 = QR.nodes, com = ref6.com, thread = ref6.thread; - if (!com.value) { - thread.value = Get.threadFromNode(this); - } - wasOnlyQuotes = QR.selected.isOnlyQuotes(); - caretPos = com.selectionStart; - com.value = com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); - range = caretPos + text.length; - com.setSelectionRange(range, range); - com.focus(); - if (wasOnlyQuotes) { - QR.selected.quotedText = com.value; - } - QR.selected.save(com); - return QR.selected.save(thread); - }, - characterCount: function() { - var count, counter; - counter = QR.nodes.charCount; - count = QR.nodes.com.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; - counter.textContent = count; - counter.hidden = count < QR.max_comment / 2; - return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); - }, - getFile: function() { - var ref; - return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); - }, - drawFile: function(e) { - var el, file, isVideo, ref; - file = (ref = QR.selected) != null ? ref.file : void 0; - if (!(file && /^(image|video)\//.test(file.type))) { - return; - } - isVideo = /^video\//.test(file); - el = $.el((isVideo ? 'video' : 'img')); - $.on(el, 'error', function() { - return QR.openError(); - }); - $.on(el, (isVideo ? 'loadeddata' : 'load'), function() { - e.target.getContext('2d').drawImage(el, 0, 0); - URL.revokeObjectURL(el.src); - return $.event('QRImageDrawn', null, e.target); - }); - return el.src = URL.createObjectURL(file); - }, - openError: function() { - var div; - div = $.el('div'); - $.extend(div, {innerHTML: "Could not open file. [More info]"}); - return QR.error(div); - }, - setFile: function(e) { - var file, name, ref, source; - ref = e.detail, file = ref.file, name = ref.name, source = ref.source; - if (name != null) { - file.name = name; - } - if (source != null) { - file.source = source; - } - QR.open(); - return QR.handleFiles([file]); - }, - 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(); - return QR.handleFiles(e.dataTransfer.files); - }, - paste: function(e) { - var blob, file, file2, item, j, len, ref, score, score2, type; - if (!e.clipboardData.items) { - return; - } - file = null; - score = -1; - ref = e.clipboardData.items; - for (j = 0, len = ref.length; j < len; j++) { - item = ref[j]; - if (!(item.kind === 'file' && (file2 = item.getAsFile()))) { - continue; - } - score2 = 2 * (file2.size <= QR.max_size) + (file2.type === 'image/png'); - if (score2 > score) { - file = file2; - score = score2; - } - } - if (file) { - type = file.type; - blob = new Blob([file], { - type: type - }); - blob.name = Conf['pastedname'] + "." + ($.getOwn(QR.extensionFromType, type) || 'jpg'); - QR.open(); - QR.handleFiles([blob]); - $.addClass(QR.nodes.el, 'dump'); - } - }, - pasteFF: function() { - var arr, blob, bstr, i, images, img, j, k, len, m, pasteArea, ref, src; - pasteArea = QR.nodes.pasteArea; - if (!pasteArea.childNodes.length) { - return; - } - images = $$('img', pasteArea); - $.rmAll(pasteArea); - for (j = 0, len = images.length; j < len; j++) { - img = images[j]; - src = img.src; - if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { - bstr = atob(m[3]); - arr = new Uint8Array(bstr.length); - for (i = k = 0, ref = bstr.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) { - arr[i] = bstr.charCodeAt(i); - } - blob = new Blob([arr], { - type: m[1] - }); - blob.name = Conf['pastedname'] + "." + m[2]; - QR.handleFiles([blob]); - } else if (/^https?:\/\//.test(src)) { - QR.handleUrl(src); - } - } - }, - handleUrl: function(urlDefault) { - QR.open(); - QR.selected.preventAutoPost(); - return CrossOrigin.permission(function() { - var url; - url = prompt('Enter a URL:', urlDefault); - if (url === null) { - return; - } - QR.nodes.fileButton.focus(); - return CrossOrigin.file(url, function(blob) { - if (blob && !/^text\//.test(blob.type)) { - return QR.handleFiles([blob]); - } else { - return QR.error("Can't load file."); - } - }); - }); - }, - handleFiles: function(files) { - var file, j, len; - if (this !== QR) { - files = slice.call(this.files); - this.value = null; - } - if (!files.length) { - return; - } - QR.cleanNotifications(); - for (j = 0, len = files.length; j < len; j++) { - file = files[j]; - QR.handleFile(file, files.length); - } - if (files.length !== 1) { - $.addClass(QR.nodes.el, 'dump'); - } - if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { - return QR.nodes.filename.focus(); - } - }, - handleFile: function(file, nfiles) { - var isText, post; - isText = /^text\//.test(file.type); - if (nfiles === 1) { - post = QR.selected; - } else { - post = QR.posts[QR.posts.length - 1]; - if ((isText ? post.com || post.pasting : post.file)) { - post = new QR.post(); - } - } - return post[isText ? 'pasteText' : 'setFile'](file); - }, - openFileInput: function() { - if (QR.nodes.fileButton.disabled) { - return; - } - QR.nodes.fileInput.click(); - return QR.nodes.fileButton.focus(); - }, - generatePostableThreadsList: function() { - var j, len, list, options, ref, thread, val; - if (!QR.nodes) { - return; - } - list = QR.nodes.thread; - options = [list.firstElementChild]; - ref = g.BOARD.threads.keys; - for (j = 0, len = ref.length; j < len; j++) { - thread = ref[j]; - options.push($.el('option', { - value: thread, - textContent: "Thread " + thread - })); - } - val = list.value; - $.rmAll(list); - $.add(list, options); - list.value = val; - if (list.value === val) { - return; - } - list.value = g.VIEW === 'thread' ? g.THREADID : 'new'; - return (g.VIEW === 'thread' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); - }, - dialog: function() { - var classList, config, dialog, event, i, items, name, node, nodes, save, setNode; - QR.nodes = nodes = { - el: dialog = UI.dialog('qr', {innerHTML: "
    ×
    No selected file
    "}) - }; - setNode = function(name, query) { - return nodes[name] = $(query, dialog); - }; - setNode('move', '.move'); - setNode('autohide', '#autohide'); - setNode('close', '.close'); - setNode('thread', 'select'); - setNode('form', 'form'); - setNode('sjisToggle', '#sjis-toggle'); - setNode('texButton', '#tex-preview-button'); - setNode('name', '[data-name=name]'); - setNode('email', '[data-name=email]'); - setNode('sub', '[data-name=sub]'); - setNode('com', '[data-name=com]'); - setNode('charCount', '#char-count'); - setNode('texPreview', '#tex-preview'); - setNode('dumpList', '#dump-list'); - setNode('addPost', '#add-post'); - setNode('oekaki', '.oekaki'); - setNode('drawButton', '#qr-draw-button'); - setNode('fileSubmit', '#file-n-submit'); - setNode('fileButton', '#qr-file-button'); - setNode('noFile', '#qr-no-file'); - setNode('filename', '#qr-filename'); - setNode('spoiler', '#qr-file-spoiler'); - setNode('oekakiButton', '#qr-oekaki-button'); - setNode('fileRM', '#qr-filerm'); - setNode('urlButton', '#url-button'); - setNode('pasteArea', '#paste-area'); - setNode('customCooldown', '#custom-cooldown-button'); - setNode('dumpButton', '#dump-button'); - setNode('status', '[type=submit]'); - setNode('flashTag', '[name=filetag]'); - setNode('fileInput', '[type=file]'); - config = g.BOARD.config; - classList = QR.nodes.el.classList; - classList.toggle('forced-anon', QR.forcedAnon); - classList.toggle('has-spoiler', QR.spoiler); - classList.toggle('has-sjis', !!config.sjis_tags); - classList.toggle('has-math', !!config.math_tags); - classList.toggle('sjis-preview', !!config.sjis_tags && Conf['sjisPreview']); - classList.toggle('show-new-thread-option', Conf['Show New Thread Option in Threads']); - if (parseInt(Conf['customCooldown'], 10) > 0) { - $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); - $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { - var customCooldownEnabled; - customCooldownEnabled = arg.customCooldownEnabled; - QR.setCustomCooldown(customCooldownEnabled); - return $.sync('customCooldownEnabled', QR.setCustomCooldown); - }); - } - QR.flagsInput(); - $.on(nodes.autohide, 'change', QR.toggleHide); - $.on(nodes.close, 'click', QR.close); - $.on(nodes.status, 'click', QR.submit); - $.on(nodes.form, 'submit', QR.submit); - $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); - $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); - $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); - $.on(nodes.addPost, 'click', function() { - return new QR.post(true); - }); - $.on(nodes.drawButton, 'click', QR.oekaki.draw); - $.on(nodes.fileButton, 'click', QR.openFileInput); - $.on(nodes.noFile, 'click', QR.openFileInput); - $.on(nodes.filename, 'focus', function() { - return $.addClass(this.parentNode, 'focus'); - }); - $.on(nodes.filename, 'blur', function() { - return $.rmClass(this.parentNode, 'focus'); - }); - $.on(nodes.spoiler, 'change', function() { - return QR.selected.nodes.spoiler.click(); - }); - $.on(nodes.oekakiButton, 'click', QR.oekaki.button); - $.on(nodes.fileRM, 'click', function() { - return QR.selected.rmFile(); - }); - $.on(nodes.urlButton, 'click', function() { - return QR.handleUrl(''); - }); - $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); - $.on(nodes.dumpButton, 'click', function() { - return nodes.el.classList.toggle('dump'); - }); - $.on(nodes.fileInput, 'change', QR.handleFiles); - window.addEventListener('focus', QR.focus, true); - window.addEventListener('blur', QR.focus, true); - $.on(d, 'click', QR.focus); - if ($.engine === 'gecko' && !window.DataTransferItemList) { - nodes.pasteArea.hidden = false; - } - new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { - childList: true - }); - items = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'flag']; - i = 0; - save = function() { - return QR.selected.save(this); - }; - while (name = items[i++]) { - if (!(node = nodes[name])) { - continue; - } - event = node.nodeName === 'SELECT' ? 'change' : 'input'; - $.on(nodes[name], event, save); - } - if ($.engine === 'gecko' && Conf['Remember QR Size']) { - $.get('QR Size', '', function(item) { - return nodes.com.style.cssText = item['QR Size']; - }); - $.on(nodes.com, 'mouseup', function(e) { - if (e.button !== 0) { - return; - } - return $.set('QR Size', this.style.cssText); - }); - } - QR.generatePostableThreadsList(); - QR.persona.load(); - new QR.post(true); - QR.status(); - QR.cooldown.setup(); - QR.captcha.init(); - $.add(d.body, dialog); - QR.captcha.setup(); - QR.oekaki.setup(); - return $.event('QRDialogCreation', null, dialog); - }, - flags: function() { - var addFlag, ref, select, textContent, value; - select = $.el('select', { - name: 'flag', - className: 'flagSelector' - }); - addFlag = function(value, textContent) { - return $.add(select, $.el('option', { - value: value, - textContent: textContent - })); - }; - addFlag('0', (g.BOARD.config.country_flags ? 'Geographic Location' : 'None')); - ref = g.BOARD.config.board_flags; - for (value in ref) { - textContent = ref[value]; - addFlag(value, textContent); - } - return select; - }, - flagsInput: function() { - var flag, nodes; - nodes = QR.nodes; - if (!nodes) { - return; - } - if (nodes.flag) { - $.rm(nodes.flag); - delete nodes.flag; - } - if (g.BOARD.config.board_flags) { - flag = QR.flags(); - flag.dataset.name = 'flag'; - flag.dataset["default"] = '0'; - nodes.flag = flag; - return $.add(nodes.form, flag); - } - }, - submit: function(e) { - var captcha, cb, err, filetag, force, formData, options, post, ref, thread, threadID; - if (e != null) { - e.preventDefault(); - } - force = e != null ? e.shiftKey : void 0; - if (QR.req) { - QR.abort(); - return; - } - $.forceSync('cooldowns'); - if (QR.cooldown.seconds) { - if (force) { - QR.cooldown.clear(); - } else { - QR.cooldown.auto = !QR.cooldown.auto; - QR.status(); - return; - } - } - post = QR.posts[0]; - delete post.quotedText; - post.forceSave(); - threadID = post.thread; - thread = g.BOARD.threads.get(threadID); - if (g.BOARD.ID === 'f' && threadID === 'new') { - filetag = QR.nodes.flashTag.value; - } - if (threadID === 'new') { - threadID = null; - if (!!g.BOARD.config.require_subject && !post.sub) { - err = 'New threads require a subject.'; - } else if (!(!!g.BOARD.config.text_only || post.file)) { - err = 'No file selected.'; - } - } else if (g.BOARD.threads.get(threadID).isClosed) { - err = 'You can\'t reply to this thread anymore.'; - } else if (!(post.com || post.file)) { - err = 'No comment or file.'; - } else if (post.file && thread.fileLimit) { - err = 'Max limit of image replies has been reached.'; - } - if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { - err || (err = 'Original comment required.'); - } - if (QR.captcha.isEnabled && !(QR.captcha === Captcha.v2 && /\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { - captcha = QR.captcha.getOne(!!threadID); - if (QR.captcha === Captcha.v2) { - captcha || (captcha = Captcha.cache.request(!!threadID)); - } - if (!captcha) { - err = 'No valid captcha.'; - QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); - } - } - QR.cleanNotifications(); - if (err && !force) { - QR.cooldown.auto = false; - QR.status(); - QR.error(err); - return; - } - QR.cooldown.auto = QR.posts.length > 1; - post.lock(); - formData = { - MAX_FILE_SIZE: QR.max_size, - mode: 'regist', - pwd: QR.persona.getPassword(), - resto: threadID, - name: !QR.forcedAnon ? post.name : void 0, - email: post.email, - sub: !(QR.forcedAnon || threadID) ? post.sub : void 0, - com: post.com, - upfile: post.file, - filetag: filetag, - spoiler: post.spoiler, - flag: post.flag - }; - options = { - responseType: 'document', - withCredentials: true, - onloadend: QR.response, - form: $.formData(formData) - }; - if (Conf['Show Upload Progress']) { - options.onprogress = function(e) { - var ref1; - if (this !== ((ref1 = QR.req) != null ? ref1.upload : void 0)) { - return; - } - if (e.loaded < e.total) { - QR.req.progress = (Math.round(e.loaded / e.total * 100)) + "%"; - } else { - QR.req.isUploadFinished = true; - QR.req.progress = '...'; - } - return QR.status(); - }; - } - cb = function(response) { - var key, val; - if (response != null) { - QR.currentCaptcha = response; - if (QR.captcha === Captcha.v2) { - if (response.challenge != null) { - options.form.append('recaptcha_challenge_field', response.challenge); - options.form.append('recaptcha_response_field', response.response); - } else { - options.form.append('g-recaptcha-response', response.response); - } - } else { - for (key in response) { - val = response[key]; - options.form.append(key, val); - } - } - } - QR.req = $.ajax("https://sys." + (location.hostname.split('.')[1]) + ".org/" + g.BOARD + "/post", options); - return QR.req.progress = '...'; - }; - if (typeof captcha === 'function') { - QR.req = { - progress: '...', - abort: function() { - if (QR.captcha === Captcha.v2) { - Captcha.cache.abort(); - } - return cb = null; - } - }; - captcha(function(response) { - if (QR.captcha === Captcha.v2 && Captcha.cache.haveCookie()) { - if (typeof cb === "function") { - cb(); - } - if (response) { - return Captcha.cache.save(response); - } - } else if (response) { - return typeof cb === "function" ? cb(response) : void 0; - } else { - delete QR.req; - post.unlock(); - QR.cooldown.auto = !!Captcha.cache.getCount(); - return QR.status(); - } - }); - } else { - cb(captcha); - } - return QR.status(); - }, - response: function() { - var URL, _, base, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; - if (this !== QR.req) { - return; - } - delete QR.req; - post = QR.posts[0]; - post.unlock(); - if ((err = (ref = this.response) != null ? ref.getElementById('errmsg') : void 0)) { - if ((ref1 = $('a', err)) != null) { - ref1.target = '_blank'; - } - } else if ((connErr = !this.response || this.response.title !== 'Post successful!')) { - err = QR.connectionError(); - if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { - Captcha.cache.save(QR.currentCaptcha); - } - } else if (this.status !== 200) { - err = "Error " + this.statusText + " (" + this.status + ")"; - } - if (!connErr) { - if (typeof (base = QR.captcha).setUsed === "function") { - base.setUsed(); - } - } - delete QR.currentCaptcha; - if (err) { - QR.errorCount = (QR.errorCount || 0) + 1; - if (/captcha|verification/i.test(err.textContent) || connErr) { - if (/mistyped/i.test(err.textContent)) { - err = 'You mistyped the CAPTCHA, or the CAPTCHA malfunctioned.'; - } else if (/expired/i.test(err.textContent)) { - err = 'This CAPTCHA is no longer valid because it has expired.'; - } - if (QR.errorCount >= 5) { - QR.cooldown.auto = false; - } else { - QR.cooldown.auto = QR.captcha.isEnabled || connErr; - QR.cooldown.addDelay(post, 2); - } - } else if (err.textContent && (m = err.textContent.match(/\d+\s+(?:minute|second)/gi)) && !/duplicate|hour/i.test(err.textContent)) { - QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); - seconds = 0; - for (j = 0, len = m.length; j < len; j++) { - mi = m[j]; - seconds += (/minute/i.test(mi) ? 60 : 1) * (+mi.match(/\d+/)[0]); - } - if (/muted/i.test(err.textContent)) { - QR.cooldown.addMute(seconds); - } else { - QR.cooldown.addDelay(post, seconds); - } - } else { - QR.cooldown.auto = false; - } - QR.captcha.setup(QR.cooldown.auto && ((ref2 = d.activeElement) === QR.nodes.status || ref2 === d.body)); - QR.status(); - QR.error(err); - return; - } - delete QR.errorCount; - h1 = $('h1', this.response); - ref3 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref3[0], threadID = ref3[1], postID = ref3[2]; - postID = +postID; - threadID = +threadID || postID; - isReply = threadID !== postID; - $.event('QRPostSuccessful', { - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID - }); - $.event('QRPostSuccessful_', { - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID - }); - postsCount = QR.posts.length - 1; - QR.cooldown.auto = postsCount && isReply; - lastPostToThread = !((function() { - var k, len1, p, ref4; - ref4 = QR.posts.slice(1); - for (k = 0, len1 = ref4.length; k < len1; k++) { - p = ref4[k]; - if (p.thread === post.thread) { - return true; - } - } - })()); - if (postsCount) { - post.rm(); - QR.captcha.setup(d.activeElement === QR.nodes.status); - } else if (Conf['Persistent QR']) { - post.rm(); - if (Conf['Auto Hide QR']) { - QR.hide(); - } else { - QR.blur(); - } - } else { - QR.close(); - } - QR.cleanNotifications(); - if (Conf['Posting Success Notifications']) { - QR.notifications.push(new Notice('success', h1.textContent, 5)); - } - QR.cooldown.add(threadID, postID); - URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : threadID !== g.THREADID && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; - if (URL) { - open = Conf['Open Post in New Tab'] || postsCount ? function() { - return $.open(URL); - } : function() { - return location.href = URL; - }; - if (threadID === postID) { - QR.waitForThread(URL, open); - } else { - open(); - } - } - return QR.status(); - }, - waitForThread: function(url, cb) { - var attempts, check; - attempts = 0; - check = function() { - return $.ajax(url, { - onloadend: function() { - attempts++; - if (attempts >= 6 || this.status === 200) { - return cb(); - } else { - return setTimeout(check, attempts * $.SECOND); - } - }, - responseType: 'text', - type: 'HEAD' - }); - }; - return check(); - }, - abort: function() { - var oldReq; - if ((oldReq = QR.req) && !QR.req.isUploadFinished) { - delete QR.req; - oldReq.abort(); - if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { - Captcha.cache.save(QR.currentCaptcha); - } - delete QR.currentCaptcha; - QR.posts[0].unlock(); - QR.cooldown.auto = false; - QR.notifications.push(new Notice('info', 'QR upload aborted.', 5)); - } - return QR.status(); - } - }; - - return QR; - -}).call(this); - -(function() { - QR.cooldown = { - seconds: 0, - delays: { - deletion: 60 - }, - init: function() { - if (!Conf['Quick Reply']) { - return; - } - this.data = Conf['cooldowns']; - this.changes = $.dict(); - return $.sync('cooldowns', this.sync); - }, - setup: function() { - var delay, ref, type; - $.extend(QR.cooldown.delays, g.BOARD.cooldowns()); - QR.cooldown.maxDelay = 0; - ref = QR.cooldown.delays; - for (type in ref) { - delay = ref[type]; - if (type !== 'thread' && type !== 'thread_global') { - QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); - } - } - QR.cooldown.isSetup = true; - return QR.cooldown.start(); - }, - start: function() { - var data; - data = QR.cooldown.data; - if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { - return; - } - QR.cooldown.isCounting = true; - return QR.cooldown.count(); - }, - sync: function(data) { - QR.cooldown.data = data || $.dict(); - return QR.cooldown.start(); - }, - add: function(threadID, postID) { - var boardID, start; - if (!Conf['Cooldown']) { - return; - } - start = Date.now(); - boardID = g.BOARD.ID; - QR.cooldown.set(boardID, start, { - threadID: threadID, - postID: postID - }); - if (threadID === postID) { - QR.cooldown.set('global', start, { - boardID: boardID, - threadID: threadID, - postID: postID - }); - } - QR.cooldown.save(); - return QR.cooldown.start(); - }, - addDelay: function(post, delay) { - var cooldown; - if (!Conf['Cooldown']) { - return; - } - cooldown = QR.cooldown.categorize(post); - cooldown.delay = delay; - QR.cooldown.set(g.BOARD.ID, Date.now(), cooldown); - QR.cooldown.save(); - return QR.cooldown.start(); - }, - addMute: function(delay) { - if (!Conf['Cooldown']) { - return; - } - QR.cooldown.set(g.BOARD.ID, Date.now(), { - type: 'mute', - delay: delay - }); - QR.cooldown.save(); - return QR.cooldown.start(); - }, - "delete": function(post) { - var base, cooldown, cooldowns, id, name; - if (!QR.cooldown.data) { - return; - } - cooldowns = ((base = QR.cooldown.data)[name = post.board.ID] || (base[name] = $.dict())); - for (id in cooldowns) { - cooldown = cooldowns[id]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - QR.cooldown.set(post.board.ID, id, null); - } - } - return QR.cooldown.save(); - }, - secondsDeletion: function(post) { - var cooldown, cooldowns, seconds, start; - if (!(QR.cooldown.data && Conf['Cooldown'])) { - return 0; - } - cooldowns = QR.cooldown.data[post.board.ID] || $.dict(); - for (start in cooldowns) { - cooldown = cooldowns[start]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); - return Math.max(seconds, 0); - } - } - return 0; - }, - categorize: function(post) { - if (post.thread === 'new') { - return { - type: 'thread' - }; - } else { - return { - type: !!post.file ? 'image' : 'reply', - threadID: +post.thread - }; - } - }, - mergeChange: function(data, scope, id, value) { - if (value) { - return (data[scope] || (data[scope] = $.dict()))[id] = value; - } else if (scope in data) { - delete data[scope][id]; - if (Object.keys(data[scope]).length === 0) { - return delete data[scope]; - } - } - }, - set: function(scope, id, value) { - var base; - QR.cooldown.mergeChange(QR.cooldown.data, scope, id, value); - return ((base = QR.cooldown.changes)[scope] || (base[scope] = $.dict()))[id] = value; - }, - save: function() { - var changes; - changes = QR.cooldown.changes; - if (!Object.keys(changes).length) { - return; - } - return $.get('cooldowns', $.dict(), function(arg) { - var cooldowns, id, ref, scope, value; - cooldowns = arg.cooldowns; - for (scope in QR.cooldown.changes) { - ref = QR.cooldown.changes[scope]; - for (id in ref) { - value = ref[id]; - QR.cooldown.mergeChange(cooldowns, scope, id, value); - } - QR.cooldown.data = cooldowns; - } - return $.set('cooldowns', cooldowns, function() { - return QR.cooldown.changes = $.dict(); - }); - }); - }, - clear: function() { - QR.cooldown.data = $.dict(); - QR.cooldown.changes = $.dict(); - QR.cooldown.auto = false; - QR.cooldown.update(); - return $.queueTask($["delete"], 'cooldowns'); - }, - update: function() { - var base, cooldown, cooldowns, elapsed, i, len, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; - if (!QR.cooldown.isCounting) { - return; - } - save = false; - nCooldowns = 0; - now = Date.now(); - ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; - seconds = 0; - if (Conf['Cooldown']) { - ref1 = [g.BOARD.ID, 'global']; - for (i = 0, len = ref1.length; i < len; i++) { - scope = ref1[i]; - cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = $.dict())); - for (start in cooldowns) { - cooldown = cooldowns[start]; - start = +start; - elapsed = Math.floor((now - start) / $.SECOND); - if (elapsed < 0) { - QR.cooldown.set(scope, start, null); - save = true; - continue; - } - if (cooldown.delay != null) { - if (cooldown.delay <= elapsed) { - QR.cooldown.set(scope, start, null); - save = true; - } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { - seconds = Math.max(seconds, cooldown.delay - elapsed); - } - continue; - } - maxDelay = cooldown.threadID !== cooldown.postID ? QR.cooldown.maxDelay : QR.cooldown.delays[scope === 'global' ? 'thread_global' : 'thread']; - if (QR.cooldown.customCooldown) { - maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); - } - if (maxDelay <= elapsed) { - QR.cooldown.set(scope, start, null); - save = true; - continue; - } - if ((type === 'thread') === (cooldown.threadID === cooldown.postID) && cooldown.boardID !== g.BOARD.ID) { - suffix = scope === 'global' ? '_global' : ''; - seconds = Math.max(seconds, QR.cooldown.delays[type + suffix] - elapsed); - if (QR.cooldown.customCooldown) { - seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); - } - } - } - nCooldowns += Object.keys(cooldowns).length; - } - } - if (save) { - QR.cooldown.save; - } - if (nCooldowns) { - clearTimeout(QR.cooldown.timeout); - QR.cooldown.timeout = setTimeout(QR.cooldown.count, $.SECOND); - } else { - delete QR.cooldown.isCounting; - } - update = seconds !== QR.cooldown.seconds; - QR.cooldown.seconds = seconds; - if (update) { - return QR.status(); - } - }, - count: function() { - QR.cooldown.update(); - if (QR.cooldown.seconds === 0 && QR.cooldown.auto && !QR.req) { - return QR.submit(); - } - } - }; - -}).call(this); - -(function() { - QR.oekaki = { - menu: { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { - return; - } - a = $.el('a', { - className: 'edit-link', - href: 'javascript:;', - textContent: 'Edit image' - }); - $.on(a, 'click', this.editFile); - return Menu.menu.addEntry({ - el: a, - order: 90, - open: function(post) { - var file; - QR.oekaki.menu.post = post; - file = post.file; - return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); - } - }); - }, - editFile: function() { - var currentTime, isVideo, post, ref; - post = QR.oekaki.menu.post; - QR.quote.call(post.nodes.post); - isVideo = post.file.isVideo; - currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; - return CrossOrigin.file(post.file.url, function(blob) { - var video; - if (!blob) { - return QR.error("Can't load file."); - } else if (isVideo) { - video = $.el('video'); - $.on(video, 'loadedmetadata', function() { - $.on(video, 'seeked', function() { - var canvas; - canvas = $.el('canvas', { - width: video.videoWidth, - height: video.videoHeight - }); - canvas.getContext('2d').drawImage(video, 0, 0); - return canvas.toBlob(function(snapshot) { - snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; - QR.handleFiles([snapshot]); - return QR.oekaki.edit(); - }); - }); - return video.currentTime = currentTime; - }); - $.on(video, 'error', function() { - return QR.openError(); - }); - return video.src = URL.createObjectURL(blob); - } else { - blob.name = post.file.name; - QR.handleFiles([blob]); - return QR.oekaki.edit(); - } - }); - } - }, - setup: function() { - return $.global(function() { - var FCX; - FCX = window.FCX; - FCX.oekakiCB = function() { - return window.Tegaki.flatten().toBlob(function(file) { - var source; - source = "oekaki-" + (Date.now()); - FCX.oekakiLatest = source; - return document.dispatchEvent(new CustomEvent('QRSetFile', { - bubbles: true, - detail: { - file: file, - name: FCX.oekakiName, - source: source - } - })); - }); - }; - if (window.Tegaki) { - return document.querySelector('#qr .oekaki').hidden = false; - } - }); - }, - load: function(cb) { - var n, onload, script, style; - if ($('script[src^="//s.4cdn.org/js/tegaki"]', d.head)) { - return cb(); - } else { - style = $.el('link', { - rel: 'stylesheet', - href: "//s.4cdn.org/css/tegaki." + (Date.now()) + ".css" - }); - script = $.el('script', { - src: "//s.4cdn.org/js/tegaki.min." + (Date.now()) + ".js" - }); - n = 0; - onload = function() { - if (++n === 2) { - return cb(); - } - }; - $.on(style, 'load', onload); - $.on(script, 'load', onload); - return $.add(d.head, [style, script]); - } - }, - draw: function() { - return $.global(function() { - var FCX, Tegaki; - Tegaki = window.Tegaki, FCX = window.FCX; - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = 'tegaki.png'; - return Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: +document.querySelector('#qr [name=oekaki-width]').value, - height: +document.querySelector('#qr [name=oekaki-height]').value, - bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' - }); - }); - }, - button: function() { - if (QR.selected.file) { - return QR.oekaki.edit(); - } else { - return QR.oekaki.toggle(); - } - }, - edit: function() { - return QR.oekaki.load(function() { - return $.global(function() { - var FCX, Tegaki, cb, error, name, source; - Tegaki = window.Tegaki, FCX = window.FCX; - name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; - source = document.getElementById('file-n-submit').dataset.source; - error = function(content) { - return document.dispatchEvent(new CustomEvent('CreateNotification', { - bubbles: true, - detail: { - type: 'warning', - content: content, - lifetime: 20 - } - })); - }; - cb = function(e) { - var canvas, selected; - if (e) { - this.removeEventListener('QRMetadata', cb, false); - } - selected = document.getElementById('selected'); - if (!(selected != null ? selected.dataset.type : void 0)) { - return error('No file to edit.'); - } - if (!/^(image|video)\//.test(selected.dataset.type)) { - return error('Not an image.'); - } - if (!selected.dataset.height) { - return error('Metadata not available.'); - } - if (selected.dataset.height === 'loading') { - selected.addEventListener('QRMetadata', cb, false); - return; - } - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = name; - Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: +selected.dataset.width, - height: +selected.dataset.height, - bgColor: 'transparent' - }); - canvas = document.createElement('canvas'); - canvas.width = canvas.naturalWidth = +selected.dataset.width; - canvas.height = canvas.naturalHeight = +selected.dataset.height; - canvas.hidden = true; - document.body.appendChild(canvas); - canvas.addEventListener('QRImageDrawn', function() { - this.remove(); - return Tegaki.onOpenImageLoaded.call(this); - }, false); - return canvas.dispatchEvent(new CustomEvent('QRDrawFile', { - bubbles: true - })); - }; - if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { - FCX.oekakiName = name; - return Tegaki.resume(); - } else { - return cb(); - } - }); - }); - }, - toggle: function() { - return QR.oekaki.load(function() { - return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; - }); - } - }; - -}).call(this); - -(function() { - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - QR.persona = { - always: {}, - types: { - name: [], - email: [], - sub: [] - }, - init: function() { - var i, item, len, ref; - if (!(Conf['Quick Reply'] || (Conf['Menu'] && Conf['Delete Link']))) { - return; - } - ref = Conf['QR.personas'].split('\n'); - for (i = 0, len = ref.length; i < len; i++) { - item = ref[i]; - QR.persona.parseItem(item.trim()); - } - }, - parseItem: function(item) { - var boards, match, ref, ref1, ref2, type, val; - if (item[0] === '#') { - return; - } - if (!(match = item.match(/(name|options|email|subject|password):"(.*)"/i))) { - return; - } - ref = match, match = ref[0], type = ref[1], val = ref[2]; - item = item.replace(match, ''); - boards = ((ref1 = item.match(/boards:([^;]+)/i)) != null ? ref1[1].toLowerCase() : void 0) || 'global'; - if (boards !== 'global' && (ref2 = g.BOARD.ID, indexOf.call(boards.split(','), ref2) < 0)) { - return; - } - if (type === 'password') { - QR.persona.pwd = val; - return; - } - if (type === 'options') { - type = 'email'; - } - if (type === 'subject') { - type = 'sub'; - } - if (/always/i.test(item)) { - QR.persona.always[type] = val; - } - if (indexOf.call(QR.persona.types[type], val) < 0) { - return QR.persona.types[type].push(val); - } - }, - load: function() { - var arr, i, len, list, ref, type, val; - ref = QR.persona.types; - for (type in ref) { - arr = ref[type]; - list = $("#list-" + type, QR.nodes.el); - for (i = 0, len = arr.length; i < len; i++) { - val = arr[i]; - if (val) { - $.add(list, $.el('option', { - textContent: val - })); - } - } - } - }, - getPassword: function() { - var m; - if (QR.persona.pwd != null) { - return QR.persona.pwd; - } else if ((m = d.cookie.match(/4chan_pass=([^;]+)/))) { - return decodeURIComponent(m[1]); - } else { - return ''; - } - }, - get: function(cb) { - return $.get('QR.persona', {}, function(arg) { - var persona; - persona = arg['QR.persona']; - return cb(persona); - }); - }, - set: function(post) { - return $.get('QR.persona', {}, function(arg) { - var persona; - persona = arg['QR.persona']; - persona = { - name: post.name, - flag: post.flag - }; - return $.set('QR.persona', persona); - }); - } - }; - -}).call(this); - -(function() { - var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - QR.post = (function() { - function _Class(select) { - this.select = bind(this.select, this); - var el, event, i, j, label, len, len1, prev, ref, ref1; - el = $.el('a', { - className: 'qr-preview', - draggable: true, - href: 'javascript:;' - }); - $.extend(el, {innerHTML: ""}); - this.nodes = { - el: el, - rm: el.firstChild, - spoiler: $('.qr-preview-spoiler input', el), - span: el.lastChild - }; - $.on(el, 'click', this.select); - $.on(this.nodes.rm, 'click', (function(_this) { - return function(e) { - e.stopPropagation(); - return _this.rm(); - }; - })(this)); - $.on(this.nodes.spoiler, 'change', (function(_this) { - return function(e) { - _this.spoiler = e.target.checked; - if (_this === QR.selected) { - QR.nodes.spoiler.checked = _this.spoiler; - } - return _this.preventAutoPost(); - }; - })(this)); - ref = $$('label', el); - for (i = 0, len = ref.length; i < len; i++) { - label = ref[i]; - $.on(label, 'click', function(e) { - return e.stopPropagation(); - }); - } - $.add(QR.nodes.dumpList, el); - ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; - for (j = 0, len1 = ref1.length; j < len1; j++) { - event = ref1[j]; - $.on(el, event.toLowerCase(), this[event]); - } - this.thread = g.VIEW === 'thread' ? g.THREADID : 'new'; - prev = QR.posts[QR.posts.length - 1]; - QR.posts.push(this); - this.nodes.spoiler.checked = this.spoiler = prev && Conf['Remember Spoiler'] ? prev.spoiler : false; - QR.persona.get((function(_this) { - return function(persona) { - _this.name = 'name' in QR.persona.always ? QR.persona.always.name : prev ? prev.name : persona.name; - _this.email = 'email' in QR.persona.always ? QR.persona.always.email : ''; - _this.sub = 'sub' in QR.persona.always ? QR.persona.always.sub : ''; - if (QR.nodes.flag) { - _this.flag = prev ? prev.flag : persona.flag && persona.flag in g.BOARD.config.board_flags ? persona.flag : void 0; - } - if (QR.selected === _this) { - return _this.load(); - } - }; - })(this)); - if (select) { - this.select(); - } - this.unlock(); - QR.captcha.moreNeeded(); - } - - _Class.prototype.rm = function() { - var base, index; - this["delete"](); - index = QR.posts.indexOf(this); - if (QR.posts.length === 1) { - new QR.post(true); - $.rmClass(QR.nodes.el, 'dump'); - } else if (this === QR.selected) { - (QR.posts[index - 1] || QR.posts[index + 1]).select(); - } - QR.posts.splice(index, 1); - QR.status(); - return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; - }; - - _Class.prototype["delete"] = function() { - $.rm(this.nodes.el); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(); - }; - - _Class.prototype.lock = function(lock) { - var i, len, name, node, ref; - if (lock == null) { - lock = true; - } - this.isLocked = lock; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler', 'flag']; - for (i = 0, len = ref.length; i < len; i++) { - name = ref[i]; - if (node = QR.nodes[name]) { - node.disabled = lock; - } - } - this.nodes.rm.style.visibility = lock ? 'hidden' : ''; - this.nodes.spoiler.disabled = lock; - return this.nodes.el.draggable = !lock; - }; - - _Class.prototype.unlock = function() { - return this.lock(false); - }; - - _Class.prototype.select = function() { - var rectEl, rectList; - if (QR.selected) { - QR.selected.nodes.el.removeAttribute('id'); - QR.selected.forceSave(); - } - QR.selected = this; - this.lock(this.isLocked); - this.nodes.el.id = 'selected'; - rectEl = this.nodes.el.getBoundingClientRect(); - rectList = this.nodes.el.parentNode.getBoundingClientRect(); - this.nodes.el.parentNode.scrollLeft += rectEl.left + rectEl.width / 2 - rectList.left - rectList.width / 2; - return this.load(); - }; - - _Class.prototype.load = function() { - var i, len, name, node, ref; - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'flag']; - for (i = 0, len = ref.length; i < len; i++) { - name = ref[i]; - if (!(node = QR.nodes[name])) { - continue; - } - node.value = this[name] || node.dataset["default"] || ''; - } - (this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); - this.showFileData(); - return QR.characterCount(); - }; - - _Class.prototype.save = function(input, forced) { - var base, name, prev; - if (input.type === 'checkbox') { - this.spoiler = input.checked; - return; - } - name = input.dataset.name; - if (name !== 'thread' && name !== 'name' && name !== 'email' && name !== 'sub' && name !== 'com' && name !== 'filename' && name !== 'flag') { - return; - } - prev = this[name] || input.dataset["default"] || null; - this[name] = input.value || input.dataset["default"] || null; - switch (name) { - case 'thread': - (this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); - QR.status(); - if (typeof (base = QR.captcha).updateThread === "function") { - base.updateThread(); - } - break; - case 'com': - this.updateComment(); - break; - case 'filename': - if (!this.file) { - return; - } - this.saveFilename(); - this.updateFilename(); - break; - case 'name': - case 'flag': - if (this[name] !== prev) { - QR.persona.set(this); - } - } - if (!forced) { - return this.preventAutoPost(); - } - }; - - _Class.prototype.forceSave = function() { - var i, len, name, node, ref; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler', 'flag']; - for (i = 0, len = ref.length; i < len; i++) { - name = ref[i]; - if (!(node = QR.nodes[name])) { - continue; - } - this.save(node, true); - } - }; - - _Class.prototype.preventAutoPost = function() { - if (QR.cooldown.auto && this === QR.posts[0]) { - QR.cooldown.update(); - if (QR.cooldown.seconds <= 5) { - return QR.cooldown.auto = false; - } - } - }; - - _Class.prototype.setComment = function(com) { - this.com = com || null; - if (this === QR.selected) { - QR.nodes.com.value = this.com; - } - return this.updateComment(); - }; - - _Class.prototype.updateComment = function() { - if (this === QR.selected) { - QR.characterCount(); - } - this.nodes.span.textContent = this.com; - QR.captcha.moreNeeded(); - if (QR.captcha === Captcha.v2) { - return Captcha.cache.prerequest(); - } - }; - - _Class.prototype.isOnlyQuotes = function() { - return (this.com || '').trim() === (this.quotedText || '').trim(); - }; - - _Class.rmErrored = function(e) { - var error, errors, i, j, len, post, ref; - e.stopPropagation(); - ref = QR.posts; - for (i = ref.length - 1; i >= 0; i += -1) { - post = ref[i]; - if (errors = post.errors) { - for (j = 0, len = errors.length; j < len; j++) { - error = errors[j]; - if (!(doc.contains(error))) { - continue; - } - post.rm(); - break; - } - } - } - }; - - _Class.prototype.error = function(className, message, link) { - var div, ref, rm, rmAll; - div = $.el('div', { - className: className - }); - $.extend(div, {innerHTML: E(message) + ((link) ? " [More info]" : "") + "
    [delete post] [delete all]"}); - (this.errors || (this.errors = [])).push(div); - ref = $$('a', div), rm = ref[0], rmAll = ref[1]; - $.on(div, 'click', (function(_this) { - return function() { - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.select(); - } - }; - })(this)); - $.on(rm, 'click', (function(_this) { - return function(e) { - e.stopPropagation(); - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.rm(); - } - }; - })(this)); - $.on(rmAll, 'click', QR.post.rmErrored); - return QR.error(div, true); - }; - - _Class.prototype.fileError = function(message, link) { - return this.error('file-error', this.filename + ": " + message, link); - }; - - _Class.prototype.dismissErrors = function(test) { - var error, i, len, ref; - if (test == null) { - test = function() { - return true; - }; - } - if (this.errors) { - ref = this.errors; - for (i = 0, len = ref.length; i < len; i++) { - error = ref[i]; - if (doc.contains(error) && test(error)) { - error.parentNode.previousElementSibling.click(); - } - } - } - }; - - _Class.prototype.setFile = function(file1) { - var ext, ref; - this.file = file1; - if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { - this.filename = "" + (Date.now() * 1000 - Math.floor(Math.random() * 365 * $.DAY * 1000)); - if (ext = this.file.name.match(QR.validExtension)) { - this.filename += ext[0]; - } - } else { - this.filename = this.file.name; - } - this.filesize = $.bytesToString(this.file.size); - this.checkSize(); - $.addClass(this.nodes.el, 'has-file'); - QR.captcha.moreNeeded(); - URL.revokeObjectURL(this.URL); - this.saveFilename(); - if (this === QR.selected) { - this.showFileData(); - } else { - this.updateFilename(); - } - this.rmMetadata(); - this.nodes.el.dataset.type = this.file.type; - this.nodes.el.style.backgroundImage = ''; - if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { - this.fileError('Unsupported file type.'); - } else if (/^(image|video)\//.test(this.file.type)) { - this.readFile(); - } - return this.preventAutoPost(); - }; - - _Class.prototype.checkSize = function() { - var max; - max = QR.max_size; - if (/^video\//.test(this.file.type)) { - max = Math.min(max, QR.max_size_video); - } - if (this.file.size > max) { - return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); - } - }; - - _Class.prototype.readFile = function() { - var el, event, isVideo, onerror, onload; - isVideo = /^video\//.test(this.file.type); - el = $.el(isVideo ? 'video' : 'img'); - if (isVideo && !el.canPlayType(this.file.type)) { - return; - } - event = isVideo ? 'loadeddata' : 'load'; - onload = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.checkDimensions(el); - _this.setThumbnail(el); - return $.event('QRMetadata', null, _this.nodes.el); - }; - })(this); - onerror = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.fileError("Corrupt " + (isVideo ? 'video' : 'image') + " or error reading metadata.", 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions#error-reading-metadata'); - URL.revokeObjectURL(el.src); - _this.nodes.el.removeAttribute('data-height'); - return $.event('QRMetadata', null, _this.nodes.el); - }; - })(this); - this.nodes.el.dataset.height = 'loading'; - $.on(el, event, onload); - $.on(el, 'error', onerror); - return el.src = URL.createObjectURL(this.file); - }; - - _Class.prototype.checkDimensions = function(el) { - var duration, height, max_height, max_width, videoHeight, videoWidth, width; - if (el.tagName === 'IMG') { - height = el.height, width = el.width; - this.nodes.el.dataset.height = height; - this.nodes.el.dataset.width = width; - if (height > QR.max_height || width > QR.max_width) { - this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - } - if (height < QR.min_height || width < QR.min_width) { - return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - } else { - videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; - this.nodes.el.dataset.height = videoHeight; - this.nodes.el.dataset.width = videoWidth; - this.nodes.el.dataset.duration = duration; - max_height = Math.min(QR.max_height, QR.max_height_video); - max_width = Math.min(QR.max_width, QR.max_width_video); - if (videoHeight > max_height || videoWidth > max_width) { - this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - } - if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - if (!isFinite(duration)) { - this.fileError('Video lacks duration metadata (try remuxing)'); - } else if (duration > QR.max_duration_video) { - this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - } - if (BoardConfig.noAudio(g.BOARD.ID) && $.hasAudio(el)) { - return this.fileError('Audio not allowed'); - } - } - }; - - _Class.prototype.setThumbnail = function(el) { - var cv, height, isVideo, s, width; - isVideo = el.tagName === 'VIDEO'; - s = 90 * 2 * window.devicePixelRatio; - if (this.file.type === 'image/gif') { - s *= 3; - } - if (isVideo) { - height = el.videoHeight; - width = el.videoWidth; - } else { - height = el.height, width = el.width; - if (height < s || width < s) { - this.URL = el.src; - this.nodes.el.style.backgroundImage = "url(" + this.URL + ")"; - return; - } - } - if (height <= width) { - width = s / height * width; - height = s; - } else { - height = s / width * height; - width = s; - } - cv = $.el('canvas'); - cv.height = height; - cv.width = width; - cv.getContext('2d').drawImage(el, 0, 0, width, height); - URL.revokeObjectURL(el.src); - return cv.toBlob((function(_this) { - return function(blob) { - _this.URL = URL.createObjectURL(blob); - return _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; - }; - })(this)); - }; - - _Class.prototype.rmFile = function() { - if (this.isLocked) { - return; - } - delete this.file; - delete this.filename; - delete this.filesize; - this.nodes.el.removeAttribute('title'); - QR.nodes.filename.removeAttribute('title'); - this.rmMetadata(); - this.nodes.el.style.backgroundImage = ''; - $.rmClass(this.nodes.el, 'has-file'); - this.showFileData(); - URL.revokeObjectURL(this.URL); - this.dismissErrors(function(error) { - return $.hasClass(error, 'file-error'); - }); - return this.preventAutoPost(); - }; - - _Class.prototype.rmMetadata = function() { - var attr, i, len, ref; - ref = ['type', 'height', 'width', 'duration']; - for (i = 0, len = ref.length; i < len; i++) { - attr = ref[i]; - this.nodes.el.removeAttribute("data-" + attr); - } - }; - - _Class.prototype.saveFilename = function() { - this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); - if (!QR.validExtension.test(this.filename)) { - return this.file.newName += "." + ($.getOwn(QR.extensionFromType, this.file.type) || 'jpg'); - } - }; - - _Class.prototype.updateFilename = function() { - var long; - long = this.filename + " (" + this.filesize + ")"; - this.nodes.el.title = long; - if (this !== QR.selected) { - return; - } - return QR.nodes.filename.title = long; - }; - - _Class.prototype.showFileData = function() { - var ref; - if (this.file) { - this.updateFilename(); - QR.nodes.filename.value = this.filename; - $.addClass(QR.nodes.oekaki, 'has-file'); - $.addClass(QR.nodes.fileSubmit, 'has-file'); - } else { - $.rmClass(QR.nodes.oekaki, 'has-file'); - $.rmClass(QR.nodes.fileSubmit, 'has-file'); - } - if (((ref = this.file) != null ? ref.source : void 0) != null) { - QR.nodes.fileSubmit.dataset.source = this.file.source; - } else { - QR.nodes.fileSubmit.removeAttribute('data-source'); - } - return QR.nodes.spoiler.checked = this.spoiler; - }; - - _Class.prototype.pasteText = function(file) { - var reader; - this.pasting = true; - this.preventAutoPost(); - reader = new FileReader(); - reader.onload = (function(_this) { - return function(e) { - var result; - result = e.target.result; - _this.setComment((_this.com ? _this.com + "\n" + result : result)); - return delete _this.pasting; - }; - })(this); - return reader.readAsText(file); - }; - - _Class.prototype.dragStart = function(e) { - var left, ref, top; - ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; - e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); - return $.addClass(this, 'drag'); - }; - - _Class.prototype.dragEnd = function() { - return $.rmClass(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 base, el, index, newIndex, oldIndex, post; - $.rmClass(this, 'over'); - if (!this.draggable) { - return; - } - el = $('.drag', this.parentNode); - index = function(el) { - return slice.call(el.parentNode.children).indexOf(el); - }; - oldIndex = index(el); - newIndex = index(this); - if (QR.posts[oldIndex].isLocked || QR.posts[newIndex].isLocked) { - return; - } - (oldIndex < newIndex ? $.after : $.before)(this, el); - post = QR.posts.splice(oldIndex, 1)[0]; - QR.posts.splice(newIndex, 0, post); - QR.status(); - return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; - }; - - return _Class; - - })(); - -}).call(this); - -QuoteBacklink = (function() { - var QuoteBacklink; - - QuoteBacklink = { - containers: $.dict(), - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Backlinks']) { - return; - } - if ((this.bottomBacklinks = Conf['Bottom Backlinks'])) { - $.addClass(doc, 'bottom-backlinks'); - } - Callbacks.Post.push({ - name: 'Quote Backlinking Part 1', - cb: this.firstNode - }); - return Callbacks.Post.push({ - name: 'Quote Backlinking Part 2', - cb: this.secondNode - }); - }, - firstNode: function() { - var a, clone, container, containers, hash, i, j, k, len, len1, len2, link, markYours, nodes, post, quote, ref, ref1; - if (this.isClone || !this.quotes.length || this.isRebuilt) { - return; - } - markYours = Conf['Mark Quotes of You'] && QuoteYou.isYou(this); - a = $.el('a', { - href: g.SITE.Build.postURL(this.board.ID, this.thread.ID, this.ID), - className: this.isHidden ? 'filtered backlink' : 'backlink', - textContent: Conf['backlink'].replace(/%(?:id|%)/g, (function(_this) { - return function(x) { - return { - '%id': _this.ID, - '%%': '%' - }[x]; - }; - })(this)) - }); - if (markYours) { - $.add(a, QuoteYou.mark.cloneNode(true)); - } - ref = this.quotes; - for (i = 0, len = ref.length; i < len; i++) { - quote = ref[i]; - containers = [QuoteBacklink.getContainer(quote)]; - if ((post = g.posts.get(quote)) && post.nodes.backlinkContainer) { - ref1 = post.clones; - for (j = 0, len1 = ref1.length; j < len1; j++) { - clone = ref1[j]; - containers.push(clone.nodes.backlinkContainer); - } - } - for (k = 0, len2 = containers.length; k < len2; k++) { - container = containers[k]; - link = a.cloneNode(true); - nodes = container.firstChild ? [$.tn(' '), link] : [link]; - if (Conf['Quote Previewing']) { - $.on(link, 'mouseover', QuotePreview.mouseover); - } - if (Conf['Quote Inlining']) { - $.on(link, 'click', QuoteInline.toggle); - if (Conf['Quote Hash Navigation']) { - hash = QuoteInline.qiQuote(link, $.hasClass(link, 'filtered')); - nodes.push(hash); - } - } - $.add(container, nodes); - } - } - }, - secondNode: function() { - var container; - if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) { - this.nodes.backlinkContainer = $('.container', this.nodes.post); - return; - } - if (!(this.isReply || Conf['OP Backlinks'])) { - return; - } - container = QuoteBacklink.getContainer(this.fullID); - this.nodes.backlinkContainer = container; - if (QuoteBacklink.bottomBacklinks) { - return $.add(this.nodes.post, container); - } else { - return $.add(this.nodes.info, container); - } - }, - getContainer: function(id) { - var base; - return (base = this.containers)[id] || (base[id] = $.el('span', { - className: 'container' - })); - } - }; - - return QuoteBacklink; - -}).call(this); - -QuoteCT = (function() { - var QuoteCT; - - QuoteCT = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Mark Cross-thread Quotes']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - this.mark = $.el('span', { - textContent: '\u00A0(Cross-thread)', - className: 'qmark-ct' - }); - return Callbacks.Post.push({ - name: 'Mark Cross-thread Quotes', - cb: this.node - }); - }, - node: function() { - var board, boardID, i, len, quotelink, ref, ref1, ref2, thread, threadID; - if (this.isClone && this.thread === this.context.thread) { - return; - } - ref = this.context, board = ref.board, thread = ref.thread; - ref1 = this.nodes.quotelinks; - for (i = 0, len = ref1.length; i < len; i++) { - quotelink = ref1[i]; - ref2 = Get.postDataFromLink(quotelink), boardID = ref2.boardID, threadID = ref2.threadID; - if (!threadID) { - continue; - } - if (this.isClone) { - $.rm($('.qmark-ct', quotelink)); - } - if (boardID === board.ID && threadID !== thread.ID) { - $.add(quotelink, QuoteCT.mark.cloneNode(true)); - } - } - } - }; - - return QuoteCT; - -}).call(this); - -QuoteInline = (function() { - var QuoteInline, - slice = [].slice; - - QuoteInline = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Inlining']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Callbacks.Post.push({ - name: 'Quote Inlining', - cb: this.node - }); - }, - node: function() { - var i, isClone, len, link, process, ref; - process = QuoteInline.process; - isClone = this.isClone; - ref = this.nodes.quotelinks.concat(slice.call(this.nodes.backlinks), this.nodes.archivelinks); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - process(link, isClone); - } - }, - process: function(link, clone) { - if (Conf['Quote Hash Navigation']) { - if (!clone) { - $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); - } - } - return $.on(link, 'click', QuoteInline.toggle); - }, - qiQuote: function(link, hidden) { - var name; - name = "hashlink"; - if (hidden) { - name += " filtered"; - } - return $.el('a', { - className: name, - textContent: '#', - href: link.href - }); - }, - toggle: function(e) { - var boardID, context, postID, quoter, ref, ref1, threadID; - if ($.modifiedClick(e)) { - return; - } - ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts.get(boardID + "." + postID)) != null ? ref1.nodes.root.offsetParent : void 0)) { - return; - } - if ($.hasClass(doc, 'catalog-mode')) { - return; - } - e.preventDefault(); - quoter = Get.postFromNode(this); - context = quoter.context; - if ($.hasClass(this, 'inlined')) { - QuoteInline.rm(this, boardID, threadID, postID, context); - } else { - if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { - return; - } - QuoteInline.add(this, boardID, threadID, postID, context, quoter); - } - return this.classList.toggle('inlined'); - }, - findRoot: function(quotelink, isBacklink) { - if (isBacklink) { - return $.x('ancestor::*[parent::*[contains(@class,"post")]][1]', quotelink); - } else { - return $.x('ancestor-or-self::*[parent::blockquote][1]', quotelink); - } - }, - add: function(quotelink, boardID, threadID, postID, context, quoter) { - var inline, isBacklink, post, qroot, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - inline = $.el('div', { - className: 'inline' - }); - inline.dataset.fullID = boardID + "." + postID; - root = QuoteInline.findRoot(quotelink, isBacklink); - $.after(root, inline); - qroot = $.x('ancestor::*[contains(@class,"postContainer")][1]', root); - $.addClass(qroot, 'hasInline'); - new Fetcher(boardID, threadID, postID, inline, quoter); - if (!((post = g.posts.get(boardID + "." + postID)) && context.thread === post.thread)) { - return; - } - if (isBacklink && Conf['Forward Hiding']) { - $.addClass(post.nodes.root, 'forwarded'); - post.forwarded++ || (post.forwarded = 1); - } - if (!Unread.posts) { - return; - } - return Unread.readSinglePost(post); - }, - rm: function(quotelink, boardID, threadID, postID, context) { - var el, inlined, isBacklink, parentNode, post, qroot, ref, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - root = QuoteInline.findRoot(quotelink, isBacklink); - root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + postID + "'][1]", root); - qroot = $.x('ancestor::*[contains(@class,"postContainer")][1]', root); - parentNode = root.parentNode; - $.rm(root); - $.event('PostsRemoved', null, parentNode); - if (!$('.inline', qroot)) { - $.rmClass(qroot, 'hasInline'); - } - if (!(el = root.firstElementChild)) { - return; - } - post = g.posts.get(boardID + "." + postID); - post.rmClone(el.dataset.clone); - if (Conf['Forward Hiding'] && isBacklink && context.thread === g.threads.get(boardID + "." + threadID) && !--post.forwarded) { - delete post.forwarded; - $.rmClass(post.nodes.root, 'forwarded'); - } - while (inlined = $('.inlined', el)) { - ref = Get.postDataFromLink(inlined), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - QuoteInline.rm(inlined, boardID, threadID, postID, context); - $.rmClass(inlined, 'inlined'); - } - } - }; - - return QuoteInline; - -}).call(this); - -QuoteOP = (function() { - var QuoteOP, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - QuoteOP = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Mark OP Quotes']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - this.mark = $.el('span', { - textContent: '\u00A0(OP)', - className: 'qmark-op' - }); - return Callbacks.Post.push({ - name: 'Mark OP Quotes', - cb: this.node - }); - }, - node: function() { - var boardID, fullID, i, postID, quotelink, quotelinks, quotes, ref, ref1; - if (this.isClone && this.thread === this.context.thread) { - return; - } - if (!(quotes = this.quotes).length) { - return; - } - quotelinks = this.nodes.quotelinks; - if (this.isClone && (ref = this.thread.fullID, indexOf.call(quotes, ref) >= 0)) { - i = 0; - while (quotelink = quotelinks[i++]) { - $.rm($('.qmark-op', quotelink)); - } - } - fullID = this.context.thread.fullID; - if (indexOf.call(quotes, fullID) < 0) { - return; - } - i = 0; - while (quotelink = quotelinks[i++]) { - ref1 = Get.postDataFromLink(quotelink), boardID = ref1.boardID, postID = ref1.postID; - if ((boardID + "." + postID) === fullID) { - $.add(quotelink, QuoteOP.mark.cloneNode(true)); - } - } - } - }; - - return QuoteOP; - -}).call(this); - -QuotePreview = (function() { - var QuotePreview, - slice = [].slice; - - QuotePreview = { - init: function() { - var ref; - if (!Conf['Quote Previewing']) { - return; - } - if (g.VIEW === 'archive') { - $.on(d, 'mouseover', function(e) { - if (e.target.nodeName === 'A' && $.hasClass(e.target, 'quotelink')) { - return QuotePreview.mouseover.call(e.target, e); - } - }); - } - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Callbacks.Post.push({ - name: 'Quote Previewing', - cb: this.node - }); - }, - node: function() { - var i, len, link, ref; - ref = this.nodes.quotelinks.concat(slice.call(this.nodes.backlinks), this.nodes.archivelinks); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - $.on(link, 'mouseover', QuotePreview.mouseover); - } - }, - mouseover: function(e) { - var boardID, i, len, origin, post, postID, posts, qp, ref, threadID; - if (($.hasClass(this, 'inlined') && !$.hasClass(doc, 'catalog-mode')) || !d.contains(this)) { - return; - } - ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - qp = $.el('div', { - id: 'qp', - className: 'dialog' - }); - $.add(Header.hover, qp); - new Fetcher(boardID, threadID, postID, qp, Get.postFromNode(this)); - UI.hover({ - root: this, - el: qp, - latestEvent: e, - endEvents: 'mouseout click', - cb: QuotePreview.mouseout - }); - if (Conf['Quote Highlighting'] && (origin = g.posts.get(boardID + "." + postID))) { - posts = [origin].concat(origin.clones); - posts.pop(); - for (i = 0, len = posts.length; i < len; i++) { - post = posts[i]; - $.addClass(post.nodes.post, 'qphl'); - } - } - }, - mouseout: function() { - var clone, i, len, post, ref, root; - if (!(root = this.el.firstElementChild)) { - return; - } - $.event('PostsRemoved', null, Header.hover); - clone = Get.postFromRoot(root); - post = clone.origin; - post.rmClone(root.dataset.clone); - if (!Conf['Quote Highlighting']) { - return; - } - ref = [post].concat(post.clones); - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - $.rmClass(post.nodes.post, 'qphl'); - } - } - }; - - return QuotePreview; - -}).call(this); - -QuoteStrikeThrough = (function() { - var QuoteStrikeThrough; - - QuoteStrikeThrough = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && (Conf['Reply Hiding Buttons'] || (Conf['Menu'] && Conf['Reply Hiding Link']) || Conf['Filter']))) { - return; - } - return Callbacks.Post.push({ - name: 'Strike-through Quotes', - cb: this.node - }); - }, - node: function() { - var boardID, i, len, postID, quotelink, ref, ref1, ref2; - if (this.isClone) { - return; - } - ref = this.nodes.quotelinks; - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - ref1 = Get.postDataFromLink(quotelink), boardID = ref1.boardID, postID = ref1.postID; - if ((ref2 = g.posts.get(boardID + "." + postID)) != null ? ref2.isHidden : void 0) { - $.addClass(quotelink, 'filtered'); - } - } - } - }; - - return QuoteStrikeThrough; - -}).call(this); - -QuoteThreading = -/* - <3 aeosynth - */ - -(function() { - var QuoteThreading; - - QuoteThreading = { - init: function() { - if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { - return; - } - this.controls = $.el('label', {innerHTML: " Threading"}); - this.threadNewLink = $.el('span', { - className: 'brackets-wrap threadnewlink', - hidden: true - }); - $.extend(this.threadNewLink, {innerHTML: "Thread New Posts"}); - this.input = $('input', this.controls); - this.input.checked = Conf['Thread Quotes']; - $.on(this.input, 'change', this.setEnabled); - $.on(this.input, 'change', this.rethread); - $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); - $.on(d, '4chanXInitFinished', (function(_this) { - return function() { - return _this.ready = true; - }; - })(this)); - Header.menu.addEntry(this.entry = { - el: this.controls, - order: 99 - }); - Callbacks.Thread.push({ - name: 'Quote Threading', - cb: this.setThread - }); - return Callbacks.Post.push({ - name: 'Quote Threading', - cb: this.node - }); - }, - parent: $.dict(), - children: $.dict(), - inserted: $.dict(), - toggleThreading: function() { - return this.setThreadingState(!Conf['Thread Quotes']); - }, - setThreadingState: function(enabled) { - this.input.checked = enabled; - this.setEnabled.call(this.input); - return this.rethread.call(this.input); - }, - setEnabled: function() { - var other, ref; - if (this.checked) { - $.set('Prune All Threads', false); - other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; - if (other != null ? other.checked : void 0) { - other.checked = false; - $.event('change', null, other); - } - } - return $.cb.checked.call(this); - }, - setThread: function() { - QuoteThreading.thread = this; - return $.asap((function() { - return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); - }), function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); - } - }); - }, - node: function() { - var ancestor, j, lastParent, len, parent, parents, quote, ref; - if (this.isFetchedQuote || this.isClone || !this.isReply) { - return; - } - parents = new Set(); - lastParent = null; - ref = this.quotes; - for (j = 0, len = ref.length; j < len; j++) { - quote = ref[j]; - if (parent = g.posts.get(quote)) { - if (!parent.isFetchedQuote && parent.isReply && parent.ID < this.ID) { - parents.add(parent.ID); - if (!lastParent || parent.ID > lastParent.ID) { - lastParent = parent; - } - } - } - } - if (!lastParent) { - return; - } - ancestor = lastParent; - while (ancestor = QuoteThreading.parent[ancestor.fullID]) { - parents["delete"](ancestor.ID); - } - if (parents.size === 1) { - return QuoteThreading.parent[this.fullID] = lastParent; - } - }, - descendants: function(post) { - var child, children, j, len, posts; - posts = [post]; - if (children = QuoteThreading.children[post.fullID]) { - for (j = 0, len = children.length; j < len; j++) { - child = children[j]; - posts = posts.concat(QuoteThreading.descendants(child)); - } - } - return posts; - }, - insert: function(post) { - var base, child, children, descendants, i, j, k, l, len, name, next, nodes, order, parent, prev, prev2, threadContainer, x; - if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { - return false; - } - descendants = QuoteThreading.descendants(post); - if (!Unread.posts.has(parent.ID)) { - if ((function() { - var j, len, x; - for (j = 0, len = descendants.length; j < len; j++) { - x = descendants[j]; - if (Unread.posts.has(x.ID)) { - return true; - } - } - })()) { - QuoteThreading.threadNewLink.hidden = false; - return false; - } - } - order = Unread.order; - children = ((base = QuoteThreading.children)[name = parent.fullID] || (base[name] = [])); - threadContainer = parent.nodes.threadContainer || $.el('div', { - className: 'threadContainer' - }); - nodes = [post.nodes.root]; - if (post.nodes.threadContainer) { - nodes.push(post.nodes.threadContainer); - } - i = children.length; - for (j = children.length - 1; j >= 0; j += -1) { - child = children[j]; - if (child.ID >= post.ID) { - i--; - } - } - if (i !== children.length) { - next = children[i]; - for (k = 0, len = descendants.length; k < len; k++) { - x = descendants[k]; - order.before(order[next.ID], order[x.ID]); - } - children.splice(i, 0, post); - $.before(next.nodes.root, nodes); - } else { - prev = parent; - while ((prev2 = QuoteThreading.children[prev.fullID]) && prev2.length) { - prev = prev2[prev2.length - 1]; - } - for (l = descendants.length - 1; l >= 0; l += -1) { - x = descendants[l]; - order.after(order[prev.ID], order[x.ID]); - } - children.push(post); - $.add(threadContainer, nodes); - } - QuoteThreading.inserted[post.fullID] = true; - if (!parent.nodes.threadContainer) { - parent.nodes.threadContainer = threadContainer; - $.addClass(parent.nodes.root, 'threadOP'); - $.after(parent.nodes.root, threadContainer); - } - return true; - }, - rethread: function() { - var nodes, posts, thread; - if (!QuoteThreading.ready) { - return; - } - thread = QuoteThreading.thread; - posts = thread.posts; - QuoteThreading.threadNewLink.hidden = true; - if (Conf['Thread Quotes']) { - posts.forEach(QuoteThreading.insert); - } else { - nodes = []; - Unread.order = new RandomAccessList(); - QuoteThreading.inserted = $.dict(); - posts.forEach(function(post) { - if (post.isFetchedQuote) { - return; - } - Unread.order.push(post); - if (post.isReply) { - nodes.push(post.nodes.root); - } - if (QuoteThreading.children[post.fullID]) { - delete QuoteThreading.children[post.fullID]; - $.rmClass(post.nodes.root, 'threadOP'); - $.rm(post.nodes.threadContainer); - return delete post.nodes.threadContainer; - } - }); - $.add(thread.nodes.root, nodes); - } - Unread.position = Unread.order.first; - Unread.updatePosition(); - Unread.setLine(true); - Unread.read(); - return Unread.update(); - } - }; - - return QuoteThreading; - -}).call(this); - -QuoteYou = (function() { - var QuoteYou; - - QuoteYou = { - init: function() { - var ref; - if (!Conf['Remember Your Posts']) { - return; - } - this.db = new DataBoard('yourPosts'); - $.sync('Remember Your Posts', function(enabled) { - return Conf['Remember Your Posts'] = enabled; - }); - $.on(d, 'QRPostSuccessful', function(e) { - var cb; - cb = PostRedirect.delay(); - return $.get('Remember Your Posts', Conf['Remember Your Posts'], function(items) { - var boardID, postID, ref, threadID; - if (!items['Remember Your Posts']) { - return; - } - ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - return QuoteYou.db.set({ - boardID: boardID, - threadID: threadID, - postID: postID, - val: true - }, cb); - }); - }); - if ((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') { - return; - } - if (Conf['Highlight Own Posts']) { - $.addClass(doc, 'highlight-own'); - } - if (Conf['Highlight Posts Quoting You']) { - $.addClass(doc, 'highlight-you'); - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - this.mark = $.el('span', { - textContent: '\u00A0(You)', - className: 'qmark-you' - }); - Callbacks.Post.push({ - name: 'Mark Quotes of You', - cb: this.node - }); - return QuoteYou.menu.init(); - }, - isYou: function(post) { - var ref; - return !!((ref = QuoteYou.db) != null ? ref.get({ - boardID: post.boardID, - threadID: post.threadID, - postID: post.ID - }) : void 0); - }, - node: function() { - var i, len, quotelink, ref; - if (this.isClone) { - return; - } - if (QuoteYou.isYou(this)) { - $.addClass(this.nodes.root, 'yourPost'); - } - if (!this.quotes.length) { - return; - } - ref = this.nodes.quotelinks; - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - if (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { - continue; - } - if (Conf['Mark Quotes of You']) { - $.add(quotelink, QuoteYou.mark.cloneNode(true)); - } - $.addClass(quotelink, 'you'); - $.addClass(this.nodes.root, 'quotesYou'); - } - }, - menu: { - init: function() { - var input, label, ref; - label = $.el('label', { - className: 'toggle-you' - }, {innerHTML: " You"}); - input = $('input', label); - $.on(input, 'change', QuoteYou.menu.toggle); - return (ref = Menu.menu) != null ? ref.addEntry({ - el: label, - order: 80, - open: function(post) { - QuoteYou.menu.post = post.origin || post; - input.checked = QuoteYou.isYou(post); - return true; - } - }) : void 0; - }, - toggle: function() { - var clone, data, i, j, len, len1, post, quotelink, quoter, ref, ref1; - post = QuoteYou.menu.post; - data = { - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID, - val: true - }; - if (this.checked) { - QuoteYou.db.set(data); - } else { - QuoteYou.db["delete"](data); - } - ref = [post].concat(post.clones); - for (i = 0, len = ref.length; i < len; i++) { - clone = ref[i]; - clone.nodes.root.classList.toggle('yourPost', this.checked); - } - ref1 = Get.allQuotelinksLinkingTo(post); - for (j = 0, len1 = ref1.length; j < len1; j++) { - quotelink = ref1[j]; - if (this.checked) { - if (Conf['Mark Quotes of You']) { - $.add(quotelink, QuoteYou.mark.cloneNode(true)); - } - } else { - $.rm($('.qmark-you', quotelink)); - } - quotelink.classList.toggle('you', this.checked); - if ($.hasClass(quotelink, 'quotelink')) { - quoter = Get.postFromNode(quotelink).nodes.root; - quoter.classList.toggle('quotesYou', !!$('.quotelink.you', quoter)); - } - } - } - }, - cb: { - seek: function(type) { - var highlight, highlighted, post, posts, result, str; - highlight = g.SITE.classes.highlight; - if ((highlighted = $("." + highlight))) { - $.rmClass(highlighted, highlight); - } - if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { - if (!(post = QuoteYou.lastRead = $('.quotesYou'))) { - new Notice('warning', 'No posts are currently quoting you, loser.', 20); - return; - } - if (QuoteYou.cb.scroll(post)) { - return; - } - } else { - post = QuoteYou.lastRead; - } - str = type + "::div[contains(@class,'quotesYou')]"; - while ((post = (result = $.X(str, post)).snapshotItem(type === 'preceding' ? result.snapshotLength - 1 : 0))) { - if (QuoteYou.cb.scroll(post)) { - return; - } - } - posts = $$('.quotesYou'); - return QuoteYou.cb.scroll(posts[type === 'following' ? 0 : posts.length - 1]); - }, - scroll: function(root) { - var node, post, sel; - post = Get.postFromRoot(root); - if (!post.nodes.post.getBoundingClientRect().height) { - return false; - } else { - QuoteYou.lastRead = root; - location.href = Get.url('post', post); - Header.scrollTo(post.nodes.post); - if (post.isReply) { - sel = "" + g.SITE.selectors.postContainer + g.SITE.selectors.highlightable.reply; - node = post.nodes.root; - if (!node.matches(sel)) { - node = $(sel, node); - } - $.addClass(node, g.SITE.classes.highlight); - } - return true; - } - } - } - }; - - return QuoteYou; - -}).call(this); - -Quotify = (function() { - var Quotify, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - Quotify = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Resurrect Quotes']) { - return; - } - $.addClass(doc, 'resurrect-quotes'); - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Callbacks.Post.push({ - name: 'Resurrect Quotes', - cb: this.node - }); - }, - node: function() { - var deadlink, i, j, len, len1, link, ref, ref1; - if (this.isClone) { - this.nodes.archivelinks = $$('a.linkify.quotelink', this.nodes.comment); - return; - } - ref = $$('a.linkify', this.nodes.comment); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - Quotify.parseArchivelink.call(this, link); - } - ref1 = $$('.deadlink', this.nodes.comment); - for (j = 0, len1 = ref1.length; j < len1; j++) { - deadlink = ref1[j]; - Quotify.parseDeadlink.call(this, deadlink); - } - }, - parseArchivelink: function(link) { - var boardID, m, postID, ref, threadID; - if (!(m = link.pathname.match(/^\/([^\/]+)\/thread\/S?(\d+)\/?$/))) { - return; - } - if ((ref = link.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') { - return; - } - boardID = m[1]; - threadID = m[2]; - postID = link.hash.match(/^#[pq]?(\d+)$|$/)[1] || threadID; - if (Redirect.to('post', { - boardID: boardID, - postID: postID - })) { - $.addClass(link, 'quotelink'); - $.extend(link.dataset, { - boardID: boardID, - threadID: threadID, - postID: postID - }); - return this.nodes.archivelinks.push(link); - } - }, - parseDeadlink: function(deadlink) { - var a, boardID, fetchable, m, post, postID, quote, quoteID, redirect, ref; - if ($.hasClass(deadlink.parentNode, 'prettyprint')) { - Quotify.fixDeadlink(deadlink); - return; - } - quote = deadlink.textContent; - if (!(postID = (ref = quote.match(/\d+$/)) != null ? ref[0] : void 0)) { - return; - } - if (postID[0] === '0') { - Quotify.fixDeadlink(deadlink); - return; - } - boardID = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : this.board.ID; - quoteID = boardID + "." + postID; - if (post = g.posts.get(quoteID)) { - if (!post.isDead) { - a = $.el('a', { - href: g.SITE.Build.postURL(boardID, post.thread.ID, postID), - className: 'quotelink', - textContent: quote - }); - } else { - a = $.el('a', { - href: g.SITE.Build.postURL(boardID, post.thread.ID, postID), - className: 'quotelink deadlink', - textContent: quote - }); - $.add(a, Post.deadMark.cloneNode(true)); - $.extend(a.dataset, { - boardID: boardID, - threadID: post.thread.ID, - postID: postID - }); - } - } else { - redirect = Redirect.to('thread', { - boardID: boardID, - threadID: 0, - postID: postID - }); - fetchable = Redirect.to('post', { - boardID: boardID, - postID: postID - }); - if (redirect || fetchable) { - a = $.el('a', { - href: redirect || 'javascript:;', - className: 'deadlink', - textContent: quote - }); - $.add(a, Post.deadMark.cloneNode(true)); - if (fetchable) { - $.addClass(a, 'quotelink'); - $.extend(a.dataset, { - boardID: boardID, - postID: postID - }); - } - } - } - if (indexOf.call(this.quotes, quoteID) < 0) { - this.quotes.push(quoteID); - } - if (!a) { - $.add(deadlink, Post.deadMark.cloneNode(true)); - return; - } - $.replace(deadlink, a); - if ($.hasClass(a, 'quotelink')) { - return this.nodes.quotelinks.push(a); - } - }, - fixDeadlink: function(deadlink) { - var el, green; - if (!(el = deadlink.previousSibling) || el.nodeName === 'BR') { - green = $.el('span', { - className: 'quote' - }); - $.before(deadlink, green); - $.add(green, deadlink); - } - return $.replace(deadlink, slice.call(deadlink.childNodes)); - } - }; - - return Quotify; - -}).call(this); - -Main = (function() { - var Main, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Main = { - init: function() { - var db, flatten, i, items, j, k, key, len, mountedCB, ref, ref1, ref2, w; - try { - w = window; - if ($.platform === 'crx') { - w = w.wrappedJSObject || w; - } - if ('4chan X antidup' in w) { - return; - } - w['4chan X antidup'] = true; - } catch (error1) {} - try { - if (window.frameElement && ((ref = window.frameElement.src) === '' || ref === 'about:blank')) { - return; - } - } catch (error1) {} - if (doc && $.hasClass(doc, 'fourchan-x')) { - return; - } - $.asap(docSet, function() { - $.addClass(doc, 'fourchan-x', 'seaweedchan'); - if ($.engine) { - return $.addClass(doc, "ua-" + $.engine); - } - }); - $.on(d, '4chanXInitFinished', function() { - if (Main.expectInitFinished) { - return delete Main.expectInitFinished; - } else { - new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); - return $.addClass(doc, 'tainted'); - } - }); - mountedCB = function() { - var cb, j, len, ref1, results; - d.removeEventListener('mounted', mountedCB, true); - Main.isMounted = true; - ref1 = Main.mountedCBs; - results = []; - for (j = 0, len = ref1.length; j < len; j++) { - cb = ref1[j]; - try { - results.push(cb()); - } catch (error1) {} - } - return results; - }; - d.addEventListener('mounted', mountedCB, true); - flatten = function(parent, obj) { - var key, val; - if (obj instanceof Array) { - Conf[parent] = $.dict.clone(obj[0]); - } else if (typeof obj === 'object') { - for (key in obj) { - val = obj[key]; - flatten(key, val); - } - } else { - Conf[parent] = obj; - } - }; - if ((ref1 = location.hostname) === 'boards.4chan.org' || ref1 === 'boards.4channel.org') { - $.global(function() { - var fromCharCode0; - fromCharCode0 = String.fromCharCode; - return String.fromCharCode = function() { - if (document.body) { - String.fromCharCode = fromCharCode0; - } else if (document.currentScript && !document.currentScript.src) { - throw Error(); - } - return fromCharCode0.apply(this, arguments); - }; - }); - $.asap(docSet, function() { - return $.onExists(doc, 'iframe[srcdoc]', $.rm); - }); - } - flatten(null, Config); - ref2 = DataBoard.keys; - for (j = 0, len = ref2.length; j < len; j++) { - db = ref2[j]; - Conf[db] = $.dict(); - } - Conf['customTitles'] = $.dict.clone({ - '4chan.org': { - boards: { - 'qa': { - 'boardTitle': { - orig: '/qa/ - Question & Answer', - title: '/qa/ - 2D/Random' - } - } - } - } - }); - Conf['boardConfig'] = { - boards: $.dict() - }; - Conf['archives'] = Redirect.archives; - Conf['selectedArchives'] = $.dict(); - Conf['cooldowns'] = $.dict(); - Conf['Index Sort'] = $.dict(); - for (i = k = 0; k < 2; i = ++k) { - Conf["Last Long Reply Thresholds " + i] = $.dict(); - } - Conf['siteProperties'] = $.dict(); - Conf['Except Archives from Encryption'] = false; - Conf['JSON Navigation'] = true; - Conf['Oekaki Links'] = true; - Conf['Show Name and Subject'] = false; - Conf['QR Shortcut'] = true; - Conf['Bottom QR Link'] = true; - Conf['Toggleable Thread Watcher'] = true; - Conf['siteSoftware'] = ''; - Conf['Use Faster Image Host'] = 'true'; - Conf['Captcha Fixes'] = true; - Conf['captchaServiceDomain'] = ''; - Conf['captchaServiceKey'] = $.dict(); - if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !SW.yotsuba.regexp.pass.test(location.href) && !SW.yotsuba.regexp.captcha.test(location.href) && !$$('script:not([src])', d).filter(function(s) { - return /this\[/.test(s.textContent); - }).length) { - ($.getSync || $.get)({ - 'jsWhitelist': Conf['jsWhitelist'] - }, function(arg) { - var jsWhitelist; - jsWhitelist = arg.jsWhitelist; - return $.addCSP("script-src " + (jsWhitelist.replace(/^#.*$/mg, '').replace(/[\s;]+/g, ' ').trim())); - }); - } - items = $.dict(); - for (key in Conf) { - items[key] = void 0; - } - items['previousversion'] = void 0; - return ($.getSync || $.get)(items, function(items) { - var ref3; - if (!$.perProtocolSettings && /\.4chan(?:nel)?\.org$/.test(location.hostname) && ((ref3 = items['Redirect to HTTPS']) != null ? ref3 : Conf['Redirect to HTTPS']) && location.protocol !== 'https:') { - location.replace('https://' + location.host + location.pathname + location.search + location.hash); - return; - } - return $.asap(docSet, function() { - var ref4, val; - if ($.cantSet) { - - } else if (items.previousversion == null) { - Main.isFirstRun = true; - Main.ready(function() { - $.set('previousversion', g.VERSION); - return Settings.open(); - }); - } else if (items.previousversion !== g.VERSION) { - Main.upgrade(items); - } - for (key in Conf) { - val = Conf[key]; - Conf[key] = (ref4 = items[key]) != null ? ref4 : val; - } - return Site.init(Main.initFeatures); - }); - }); - }, - upgrade: function(items) { - var changes, previousversion; - previousversion = items.previousversion; - changes = Settings.upgrade(items, previousversion); - items.previousversion = changes.previousversion = g.VERSION; - return $.set(changes, function() { - var el, ref; - if ((ref = items['Show Updated Notifications']) != null ? ref : true) { - el = $.el('span', {innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "."}); - return new Notice('info', el, 15); - } - }); - }, - parseURL: function(site, url) { - var pathname, r, ref; - if (site == null) { - site = g.SITE; - } - if (url == null) { - url = location; - } - r = {}; - if (!site) { - return r; - } - r.siteID = site.ID; - if (typeof site.isBoardlessPage === "function" ? site.isBoardlessPage(url) : void 0) { - return r; - } - pathname = url.pathname.split(/\/+/); - r.boardID = pathname[1]; - if (site.isFileURL(url)) { - r.VIEW = 'file'; - } else if (typeof site.isAuxiliaryPage === "function" ? site.isAuxiliaryPage(url) : void 0) { - - } else if ((ref = pathname[2]) === 'thread' || ref === 'res') { - r.VIEW = 'thread'; - r.threadID = r.THREADID = +pathname[3].replace(/\.\w+$/, ''); - } else if (pathname[2] === 'archive' && pathname[3] === 'res') { - r.VIEW = 'thread'; - r.threadID = r.THREADID = +pathname[4].replace(/\.\w+$/, ''); - r.threadArchived = true; - } else if (/^(?:catalog|archive)(?:\.\w+)?$/.test(pathname[2])) { - r.VIEW = pathname[2].replace(/\.\w+$/, ''); - } else if (/^(?:index|\d*)(?:\.\w+)?$/.test(pathname[2])) { - r.VIEW = 'index'; - } - return r; - }, - initFeatures: function() { - var base, err, feature, j, len, name, ref, ref1; - $.global(function() { - document.documentElement.classList.add('js-enabled'); - return window.FCX = {}; - }); - Main.jsEnabled = $.hasClass(doc, 'js-enabled'); - if (typeof $.ajaxPageInit === "function") { - $.ajaxPageInit(); - } - $.extend(g, Main.parseURL()); - if (g.boardID) { - g.BOARD = new Board(g.boardID); - } - if (!g.VIEW) { - if (typeof (base = g.SITE).initAuxiliary === "function") { - base.initAuxiliary(); - } - return; - } - if (g.VIEW === 'file') { - $.asap((function() { - return d.readyState !== 'loading'; - }), function() { - var base1, pathname, video; - if (g.SITE.software === 'yotsuba' && Conf['404 Redirect'] && (typeof (base1 = g.SITE).is404 === "function" ? base1.is404() : void 0)) { - pathname = location.pathname.split(/\/+/); - return Redirect.navigate('file', { - boardID: g.BOARD.ID, - filename: pathname[pathname.length - 1] - }); - } else if (video = $('video')) { - if (Conf['Volume in New Tab']) { - Volume.setup(video); - } - if (Conf['Loop in New Tab']) { - video.loop = true; - video.controls = false; - video.play(); - return ImageCommon.addControls(video); - } - } - }); - return; - } - g.threads = new SimpleDict(); - g.posts = new SimpleDict(); - $.onExists(doc, 'body', Main.initStyle); - ref = Main.features; - for (j = 0, len = ref.length; j < len; j++) { - ref1 = ref[j], name = ref1[0], feature = ref1[1]; - if (g.SITE.disabledFeatures && indexOf.call(g.SITE.disabledFeatures, name) >= 0) { - continue; - } - try { - feature.init(); - } catch (error1) { - err = error1; - Main.handleErrors({ - message: "\"" + name + "\" initialization crashed.", - error: err - }); - } - } - return $.ready(Main.initReady); - }, - initStyle: function() { - var keyboard, ref; - if (!Main.isThisPageLegit()) { - return; - } - if ((ref = $('link[href*=mobile]', d.head)) != null) { - ref.disabled = true; - } - doc.dataset.host = location.host; - $.addClass(doc, "sw-" + g.SITE.software); - $.addClass(doc, g.VIEW === 'thread' ? 'thread-view' : g.VIEW); - $.onExists(doc, '.ad-cnt, .adg-rects > .desktop', function(ad) { - return $.onExists(ad, 'img, iframe', function() { - return $.addClass(doc, 'ads-loaded'); - }); - }); - if (Conf['Autohiding Scrollbar']) { - $.addClass(doc, 'autohiding-scrollbar'); - } - $.ready(function() { - if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { - Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; - $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); - return $.toggleClass(doc, 'autohiding-scrollbar'); - } - }); - $.addStyle(CSS.sub(CSS.boards), 'fourchanx-css'); - Main.bgColorStyle = $.el('style', { - id: 'fourchanx-bgcolor-css' - }); - keyboard = false; - $.on(d, 'mousedown', function() { - return keyboard = false; - }); - $.on(d, 'keydown', function(e) { - if (e.keyCode === 9) { - return keyboard = true; - } - }); - window.addEventListener('focus', (function() { - return doc.classList.toggle('keyboard-focus', keyboard); - }), true); - return Main.setClass(); - }, - setClass: function() { - var j, knownStyles, len, mainStyleSheet, ref, ref1, setStyle, style, styleSheet, styleSheets; - knownStyles = ['yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'photon', 'tomorrow', 'spooky']; - if (g.SITE.software === 'yotsuba' && g.VIEW === 'catalog') { - if ((mainStyleSheet = $.id('base-css'))) { - style = (ref = mainStyleSheet.href.match(/catalog_(\w+)/)) != null ? ref[1].replace('_new', '').replace(/_+/g, '-') : void 0; - if (indexOf.call(knownStyles, style) >= 0) { - $.addClass(doc, style); - return; - } - } - } - style = mainStyleSheet = styleSheets = null; - setStyle = function() { - var bgColor, css, div, j, len, rgb, s, styleSheet; - if (g.SITE.software === 'yotsuba') { - $.rmClass(doc, style); - style = null; - for (j = 0, len = styleSheets.length; j < len; j++) { - styleSheet = styleSheets[j]; - if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { - style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); - if (style === '_special') { - style = styleSheet.href.match(/[a-z]*(?=[^\/]*$)/)[0]; - } - if (indexOf.call(knownStyles, style) < 0) { - style = null; - } - break; - } - } - if (style) { - $.addClass(doc, style); - $.rm(Main.bgColorStyle); - return; - } - } - div = g.SITE.bgColoredEl(); - div.style.position = 'absolute'; - div.style.visibility = 'hidden'; - $.add(d.body, div); - bgColor = window.getComputedStyle(div).backgroundColor; - $.rm(div); - rgb = bgColor.match(/[\d.]+/g); - if (!/^rgb\(/.test(bgColor)) { - s = window.getComputedStyle(d.body); - bgColor = s.backgroundColor + " " + s.backgroundImage + " " + s.backgroundRepeat + " " + s.backgroundPosition; - } - css = ".dialog, .suboption-list > div:last-of-type, :root.catalog-hover-expand .catalog-container:hover > .post {\n background: " + bgColor + ";\n}\n.unread-mark-read {\n background-color: rgba(" + (rgb.slice(0, 3).join(', ')) + ", " + (0.5 * (rgb[3] || 1)) + ");\n}"; - if ($.luma(rgb) < 100) { - css += ".watch-thread-link {\n background-image: url(\"data:image/svg+xml,\");\n}"; - } - Main.bgColorStyle.textContent = css; - return $.after($.id('fourchanx-css'), Main.bgColorStyle); - }; - $.onExists(d.head, g.SITE.selectors.styleSheet, function(el) { - mainStyleSheet = el; - if (g.SITE.software === 'yotsuba') { - styleSheets = $$('link[rel="alternate stylesheet"]', d.head); - } - new MutationObserver(setStyle).observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - $.on(mainStyleSheet, 'load', setStyle); - return setStyle(); - }); - if (!mainStyleSheet) { - ref1 = $$('link[rel="stylesheet"]', d.head); - for (j = 0, len = ref1.length; j < len; j++) { - styleSheet = ref1[j]; - $.on(styleSheet, 'load', setStyle); - } - return setStyle(); - } - }, - initReady: function() { - var base, base1, msg; - if (typeof (base = g.SITE).is404 === "function" ? base.is404() : void 0) { - if (g.VIEW === 'thread') { - ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { - if (Conf['404 Redirect']) { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - threadID: g.THREADID, - postID: +location.hash.match(/\d+/) - }, "/" + g.BOARD + "/"); - } - }); - } - return; - } - if (typeof (base1 = g.SITE).isIncomplete === "function" ? base1.isIncomplete() : void 0) { - msg = $.el('div', {innerHTML: "The page didn't load completely.
    Some features may not work unless you reload."}); - $.on($('a', msg), 'click', function() { - return location.reload(); - }); - new Notice('warning', msg); - } - if (g.VIEW === 'catalog') { - return Main.initCatalog(); - } else if (!Index.enabled) { - if (g.SITE.awaitBoard) { - return g.SITE.awaitBoard(Main.initThread); - } else { - return Main.initThread(); - } - } else { - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - } - }, - initThread: function() { - var base, base1, board, errors, posts, ref, s, threads; - s = g.SITE.selectors; - if ((board = $(((ref = s.boardFor) != null ? ref[g.VIEW] : void 0) || s.board))) { - threads = []; - posts = []; - errors = []; - try { - if (typeof (base = g.SITE).preParsingFixes === "function") { - base.preParsingFixes(board); - } - } catch (error1) {} - Main.addThreadsObserver = new MutationObserver(Main.addThreads); - Main.addPostsObserver = new MutationObserver(Main.addPosts); - Main.addThreadsObserver.observe(board, { - childList: true - }); - Main.parseThreads($$(s.thread, board), threads, posts, errors); - if (errors.length) { - Main.handleErrors(errors); - } - if (g.VIEW === 'thread') { - if (g.threadArchived) { - threads[0].isArchived = true; - threads[0].kill(); - } - if (typeof (base1 = g.SITE).parseThreadMetadata === "function") { - base1.parseThreadMetadata(threads[0]); - } - } - Main.callbackNodes('Thread', threads); - return Main.callbackNodesDB('Post', posts, function() { - var j, len, post; - for (j = 0, len = posts.length; j < len; j++) { - post = posts[j]; - QuoteThreading.insert(post); - } - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - }); - } else { - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - } - }, - parseThreads: function(threadRoots, threads, posts, errors) { - var boardID, boardObj, j, len, postRoots, ref, thread, threadID, threadRoot; - for (j = 0, len = threadRoots.length; j < len; j++) { - threadRoot = threadRoots[j]; - boardObj = (boardID = threadRoot.dataset.board) ? (boardID = encodeURIComponent(boardID), g.boards[boardID] || new Board(boardID)) : g.BOARD; - threadID = +threadRoot.id.match(/\d*$/)[0]; - if (!threadID || ((ref = boardObj.threads.get(threadID)) != null ? ref.nodes.root : void 0)) { - return; - } - thread = new Thread(threadID, boardObj); - thread.nodes.root = threadRoot; - threads.push(thread); - postRoots = $$(g.SITE.selectors.postContainer, threadRoot); - if (g.SITE.isOPContainerThread) { - postRoots.unshift(threadRoot); - } - Main.parsePosts(postRoots, thread, posts, errors); - Main.addPostsObserver.observe(threadRoot, { - childList: true - }); - } - }, - parsePosts: function(postRoots, thread, posts, errors) { - var err, j, len, postRoot; - for (j = 0, len = postRoots.length; j < len; j++) { - postRoot = postRoots[j]; - if (!(postRoot.dataset.fullID && g.posts.get(postRoot.dataset.fullID)) && $(g.SITE.selectors.comment, postRoot)) { - try { - posts.push(new Post(postRoot, thread, thread.board)); - } catch (error1) { - err = error1; - errors.push({ - message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.", - error: err, - html: postRoot.outerHTML - }); - } - } - } - }, - addThreads: function(records) { - var errors, j, k, len, len1, node, posts, record, ref, threadRoots, threads; - threadRoots = []; - for (j = 0, len = records.length; j < len; j++) { - record = records[j]; - ref = record.addedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - if (node.nodeType === Node.ELEMENT_NODE && node.matches(g.SITE.selectors.thread)) { - threadRoots.push(node); - } - } - } - if (!threadRoots.length) { - return; - } - threads = []; - posts = []; - errors = []; - Main.parseThreads(threadRoots, threads, posts, errors); - if (errors.length) { - Main.handleErrors(errors); - } - Main.callbackNodes('Thread', threads); - return Main.callbackNodesDB('Post', posts, function() { - return $.event('PostsInserted', null, records[0].target); - }); - }, - addPosts: function(records) { - var anyRemoved, el, errors, j, k, l, len, len1, len2, n, node, postRoots, posts, record, ref, ref1, ref2, thread, threads, threadsRM; - threads = []; - threadsRM = []; - posts = []; - errors = []; - for (j = 0, len = records.length; j < len; j++) { - record = records[j]; - thread = Get.threadFromRoot(record.target); - postRoots = []; - ref = record.addedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - if (node.nodeType === Node.ELEMENT_NODE) { - if (node.matches(g.SITE.selectors.postContainer) || (node = $(g.SITE.selectors.postContainer, node))) { - postRoots.push(node); - } - } - } - n = posts.length; - Main.parsePosts(postRoots, thread, posts, errors); - if (posts.length > n && indexOf.call(threads, thread) < 0) { - threads.push(thread); - } - anyRemoved = false; - ref1 = record.removedNodes; - for (l = 0, len2 = ref1.length; l < len2; l++) { - el = ref1[l]; - if (((ref2 = Get.postFromRoot(el)) != null ? ref2.nodes.root : void 0) === el && !doc.contains(el)) { - anyRemoved = true; - break; - } - } - if (anyRemoved && indexOf.call(threadsRM, thread) < 0) { - threadsRM.push(thread); - } - } - if (errors.length) { - Main.handleErrors(errors); - } - return Main.callbackNodesDB('Post', posts, function() { - var len3, len4, m, o; - for (m = 0, len3 = threads.length; m < len3; m++) { - thread = threads[m]; - $.event('PostsInserted', null, thread.nodes.root); - } - for (o = 0, len4 = threadsRM.length; o < len4; o++) { - thread = threadsRM[o]; - $.event('PostsRemoved', null, thread.nodes.root); - } - }); - }, - initCatalog: function() { - var board, errors, s, threads; - s = g.SITE.selectors.catalog; - if (s && (board = $(s.board))) { - threads = []; - errors = []; - Main.addCatalogThreadsObserver = new MutationObserver(Main.addCatalogThreads); - Main.addCatalogThreadsObserver.observe(board, { - childList: true - }); - Main.parseCatalogThreads($$(s.thread, board), threads, errors); - if (errors.length) { - Main.handleErrors(errors); - } - Main.callbackNodes('CatalogThreadNative', threads); - } - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - }, - parseCatalogThreads: function(threadRoots, threads, errors) { - var err, j, len, ref, thread, threadRoot; - for (j = 0, len = threadRoots.length; j < len; j++) { - threadRoot = threadRoots[j]; - try { - thread = new CatalogThreadNative(threadRoot); - if (((ref = thread.thread.catalogViewNative) != null ? ref.nodes.root : void 0) !== threadRoot) { - thread.thread.catalogViewNative = thread; - threads.push(thread); - } - } catch (error1) { - err = error1; - errors.push({ - message: "Parsing of Catalog Thread No." + ((threadRoot.dataset.id || threadRoot.id).match(/\d+/)) + " failed. Thread will be skipped.", - error: err, - html: threadRoot.outerHTML - }); - } - } - }, - addCatalogThreads: function(records) { - var errors, j, k, len, len1, node, record, ref, threadRoots, threads; - threadRoots = []; - for (j = 0, len = records.length; j < len; j++) { - record = records[j]; - ref = record.addedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - if (node.nodeType === Node.ELEMENT_NODE && node.matches(g.SITE.selectors.catalog.thread)) { - threadRoots.push(node); - } - } - } - if (!threadRoots.length) { - return; - } - threads = []; - errors = []; - Main.parseCatalogThreads(threadRoots, threads, errors); - if (errors.length) { - Main.handleErrors(errors); - } - return Main.callbackNodes('CatalogThreadNative', threads); - }, - callbackNodes: function(klass, nodes) { - var cb, i, node; - i = 0; - cb = Callbacks[klass]; - while (node = nodes[i++]) { - cb.execute(node); - } - }, - callbackNodesDB: function(klass, nodes, cb) { - var cbs, fn, i, softTask; - i = 0; - cbs = Callbacks[klass]; - fn = function() { - var node; - if (!(node = nodes[i])) { - return false; - } - cbs.execute(node); - return ++i % 25; - }; - softTask = function() { - while (fn()) { - continue; - } - if (!nodes[i]) { - if (cb) { - cb(); - } - return; - } - return setTimeout(softTask, 0); - }; - return softTask(); - }, - handleErrors: function(errors) { - var div, enabled, error, j, len, logs, msg; - if (d.body && $.hasClass(d.body, 'fourchan_x') && !$.hasClass(doc, 'tainted')) { - new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); - $.addClass(doc, 'tainted'); - } - if (g.SITE.testNativeExtension && !$.hasClass(doc, 'tainted')) { - enabled = g.SITE.testNativeExtension().enabled; - if (enabled) { - $.addClass(doc, 'tainted'); - if (Conf['Disable Native Extension'] && !Main.isFirstRun) { - msg = $.el('div', {innerHTML: "Failed to disable the native extension. You may need to block it."}); - new Notice('error', msg); - } - } - } - if (!(errors instanceof Array)) { - error = errors; - } else if (errors.length === 1) { - error = errors[0]; - } - if (error) { - new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); - return; - } - div = $.el('div', {innerHTML: E(errors.length) + " errors occurred." + (Main.reportLink(errors)).innerHTML + " [show]"}); - $.on(div.lastElementChild, 'click', function() { - var ref; - return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; - }); - logs = $.el('div', { - hidden: true - }); - for (j = 0, len = errors.length; j < len; j++) { - error = errors[j]; - $.add(logs, Main.parseError(error)); - } - return new Notice('error', [div, logs], 30); - }, - parseError: function(data, reportLink) { - var context, error, lines, message, ref, ref1; - c.error(data.message, data.error.stack); - message = $.el('div', {innerHTML: E(data.message) + ((reportLink) ? (reportLink).innerHTML : "")}); - error = $.el('div', { - textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') - }); - lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; - context = $.el('div', { - textContent: "(4chan X ccd0 v" + g.VERSION + " " + $.platform + " on " + $.engine + lines + ")" - }); - return [message, error, context]; - }, - reportLink: function(errors) { - var addDetails, data, details, info, title, url; - data = errors[0]; - title = data.message; - if (errors.length > 1) { - title += " (+" + (errors.length - 1) + " other errors)"; - } - details = ''; - addDetails = function(text) { - if (!(encodeURIComponent(title + details + text + '\n').length > 8143)) { - return details += text + '\n'; - } - }; - addDetails("[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " " + $.platform + "\nURL: " + location.href + "\nUser agent: " + navigator.userAgent); - if ($.platform === 'userscript' && (info = typeof GM !== "undefined" && GM !== null ? GM.info : (typeof GM_info !== "undefined" && GM_info !== null ? GM_info : void 0))) { - addDetails("Userscript manager: " + info.scriptHandler + " " + info.version); - } - addDetails('\n' + data.error); - if (data.error.stack) { - addDetails(data.error.stack.replace(data.error.toString(), '').trim()); - } - if (data.html) { - addDetails('\n`' + data.html + '`'); - } - details = details.replace(/file:\/{3}.+\//g, ''); - url = 'https://github.com/ccd0/4chan-x/issues'.replace('%title', encodeURIComponent(title)).replace('%details', encodeURIComponent(details)); - return {innerHTML: " [report]"}; - }, - isThisPageLegit: function() { - if (!('thisPageIsLegit' in Main)) { - Main.thisPageIsLegit = g.SITE.isThisPageLegit ? g.SITE.isThisPageLegit() : !/^[45]\d\d\b/.test(document.title) && !/\.(?:json|rss)$/.test(location.pathname); - } - return Main.thisPageIsLegit; - }, - ready: function(cb) { - return $.ready(function() { - if (Main.isThisPageLegit()) { - return cb(); - } - }); - }, - mounted: function(cb) { - if (Main.isMounted) { - return cb(); - } else { - return Main.mountedCBs.push(cb); - } - }, - mountedCBs: [], - features: [['Polyfill', Polyfill], ['Board Configuration', BoardConfig], ['Normalize URL', NormalizeURL], ['Delay Redirect on Post', PostRedirect], ['Captcha Configuration', Captcha.replace], ['Image Host Rewriting', ImageHost], ['Redirect', Redirect], ['Header', Header], ['Catalog Links', CatalogLinks], ['Settings', Settings], ['Index Generator', Index], ['Disable Autoplay', AntiAutoplay], ['Announcement Hiding', PSAHiding], ['Fourchan thingies', Fourchan], ['Tinyboard Glue', Tinyboard], ['Color User IDs', IDColor], ['Highlight by User ID', IDHighlight], ['Count Posts by ID', IDPostCount], ['Custom CSS', CustomCSS], ['Thread Links', ThreadLinks], ['Linkify', Linkify], ['Reveal Spoilers', RemoveSpoilers], ['Resurrect Quotes', Quotify], ['Filter', Filter], ['Thread Hiding Buttons', ThreadHiding], ['Reply Hiding Buttons', PostHiding], ['Recursive', Recursive], ['Strike-through Quotes', QuoteStrikeThrough], ['Quick Reply Personas', QR.persona], ['Quick Reply', QR], ['Cooldown', QR.cooldown], ['Post Jumper', PostJumper], ['Pass Link', PassLink], ['Menu', Menu], ['Index Generator (Menu)', Index.menu], ['Report Link', ReportLink], ['Copy Text Link', CopyTextLink], ['Thread Hiding (Menu)', ThreadHiding.menu], ['Reply Hiding (Menu)', PostHiding.menu], ['Delete Link', DeleteLink], ['Filter (Menu)', Filter.menu], ['Edit Link', QR.oekaki.menu], ['Download Link', DownloadLink], ['Archive Link', ArchiveLink], ['Quote Inlining', QuoteInline], ['Quote Previewing', QuotePreview], ['Quote Backlinks', QuoteBacklink], ['Mark Quotes of You', QuoteYou], ['Mark OP Quotes', QuoteOP], ['Mark Cross-thread Quotes', QuoteCT], ['Anonymize', Anonymize], ['Time Formatting', Time], ['Relative Post Dates', RelativeDates], ['File Info Formatting', FileInfo], ['Fappe Tyme', FappeTyme], ['Gallery', Gallery], ['Gallery (menu)', Gallery.menu], ['Sauce', Sauce], ['Image Expansion', ImageExpand], ['Image Expansion (Menu)', ImageExpand.menu], ['Reveal Spoiler Thumbnails', RevealSpoilers], ['Image Loading', ImageLoader], ['Image Hover', ImageHover], ['Volume Control', Volume], ['WEBM Metadata', Metadata], ['Comment Expansion', ExpandComment], ['Thread Expansion', ExpandThread], ['Favicon', Favicon], ['Unread', Unread], ['Unread Line in Index', UnreadIndex], ['Quote Threading', QuoteThreading], ['Thread Stats', ThreadStats], ['Thread Updater', ThreadUpdater], ['Thread Watcher', ThreadWatcher], ['Thread Watcher (Menu)', ThreadWatcher.menu], ['Mark New IPs', MarkNewIPs], ['Index Navigation', Nav], ['Keybinds', Keybinds], ['Banner', Banner], ['Announcements', PSA], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning], ['Mod Contact Links', ModContact]] - }; - - return Main; - -}).call(this); - -Main.init(); - -})(); diff --git a/builds/4chan-X-noupdate.user.js b/builds/4chan-X-noupdate.user.js deleted file mode 100644 index 829078892a..0000000000 --- a/builds/4chan-X-noupdate.user.js +++ /dev/null @@ -1,27999 +0,0 @@ -// ==UserScript== -// @name 4chan X -// @version 1.14.22.4 -// @minGMVer 1.14 -// @minFFVer 26 -// @namespace 4chan-X -// @description 4chan X is a script that adds various features to anonymous imageboards. -// @license MIT; https://github.com/ccd0/4chan-x/blob/master/LICENSE -// @include http://boards.4chan.org/* -// @include https://boards.4chan.org/* -// @include http://sys.4chan.org/* -// @include https://sys.4chan.org/* -// @include http://www.4chan.org/* -// @include https://www.4chan.org/* -// @include http://boards.4channel.org/* -// @include https://boards.4channel.org/* -// @include http://sys.4channel.org/* -// @include https://sys.4channel.org/* -// @include http://www.4channel.org/* -// @include https://www.4channel.org/* -// @include http://i.4cdn.org/* -// @include https://i.4cdn.org/* -// @include http://is.4chan.org/* -// @include https://is.4chan.org/* -// @include http://is2.4chan.org/* -// @include https://is2.4chan.org/* -// @include http://is.4channel.org/* -// @include https://is.4channel.org/* -// @include http://is2.4channel.org/* -// @include https://is2.4channel.org/* -// @include https://erischan.org/* -// @include https://www.erischan.org/* -// @include https://fufufu.moe/* -// @include https://gnfos.com/* -// @include https://himasugi.blog/* -// @include https://www.himasugi.blog/* -// @include https://kakashinenpo.com/* -// @include https://www.kakashinenpo.com/* -// @include https://kissu.moe/* -// @include https://www.kissu.moe/* -// @include https://lainchan.org/* -// @include https://www.lainchan.org/* -// @include https://merorin.com/* -// @include https://ota-ch.com/* -// @include https://www.ota-ch.com/* -// @include https://ponyville.us/* -// @include https://www.ponyville.us/* -// @include https://smuglo.li/* -// @include https://notso.smuglo.li/* -// @include https://smugloli.net/* -// @include https://smug.nepu.moe/* -// @include https://sportschan.org/* -// @include https://www.sportschan.org/* -// @include https://sushigirl.us/* -// @include https://www.sushigirl.us/* -// @include https://tvch.moe/* -// @exclude http://www.4chan.org/advertise -// @exclude https://www.4chan.org/advertise -// @exclude http://www.4chan.org/advertise?* -// @exclude https://www.4chan.org/advertise?* -// @exclude http://www.4chan.org/donate -// @exclude https://www.4chan.org/donate -// @exclude http://www.4chan.org/donate?* -// @exclude https://www.4chan.org/donate?* -// @exclude http://www.4channel.org/advertise -// @exclude https://www.4channel.org/advertise -// @exclude http://www.4channel.org/advertise?* -// @exclude https://www.4channel.org/advertise?* -// @exclude http://www.4channel.org/donate -// @exclude https://www.4channel.org/donate -// @exclude http://www.4channel.org/donate?* -// @exclude https://www.4channel.org/donate?* -// @connect 4chan.org -// @connect 4channel.org -// @connect 4cdn.org -// @connect 4chenz.github.io -// @connect archive.4plebs.org -// @connect warosu.org -// @connect desuarchive.org -// @connect boards.fireden.net -// @connect arch.b4k.co -// @connect archived.moe -// @connect thebarchive.com -// @connect archiveofsins.com -// @connect www.tokyochronos.net -// @connect archive.palanq.win -// @connect eientei.xyz -// @connect api.clyp.it -// @connect api.dailymotion.com -// @connect api.github.com -// @connect soundcloud.com -// @connect api.streamable.com -// @connect vimeo.com -// @connect www.youtube.com -// @connect * -// @grant GM_getValue -// @grant GM_setValue -// @grant GM_deleteValue -// @grant GM_listValues -// @grant GM_addValueChangeListener -// @grant GM_openInTab -// @grant GM_xmlhttpRequest -// @grant GM.getValue -// @grant GM.setValue -// @grant GM.deleteValue -// @grant GM.listValues -// @grant GM.openInTab -// @grant GM.xmlHttpRequest -// @run-at document-start -// @updateURL https://noupdate.invalid/ -// @downloadURL https://noupdate.invalid/ -// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAF5JREFUeNrtkTESABAQxPD/R6tsE2dUGYUtFJvLDKf93KevHJAjpBorAQWSBIKqFASC4G0pCAkm4GfaEvgYXl0T6HBaE97f0vmnfYHbZOMLZCx9ISdKWwjOWZSC8GYm4SUGwfYgqI4AAAAASUVORK5CYII= -// ==/UserScript== - -/* -* 4chan X -* -* Licensed under the MIT license. -* https://github.com/ccd0/4chan-x/blob/master/LICENSE -* -* Appchan X Copyright © 2013-2016 Zixaphir -* http://zixaphir.github.io/appchan-x/ -* 4chan x Copyright © 2009-2011 James Campos -* https://github.com/aeosynth/4chan-x -* 4chan x Copyright © 2012-2014 Nicolas Stepien -* https://4chan-x.just-believe.in/ -* 4chan x Copyright © 2013-2014 Jordan Bates -* http://seaweedchan.github.io/4chan-x/ -* 4chan x Copyright © 2012-2013 ihavenoface -* http://ihavenoface.github.io/4chan-x/ -* 4chan SS Copyright © 2011-2013 Ahodesuka -* https://github.com/ahodesuka/4chan-Style-Script/ -* -* 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 -* detharonil -* -* All the people who've taken the time to write bug reports. -* -* Thank you. -*/ - -/* -* Contains data from external sources: -* -* src/Monitoring/ThreadUpdater/beep.wav from http://freesound.org/people/pierrecartoons1979/sounds/90112/ -* cc-by-nc-3.0 -* -* Font Awesome by Dave Gandy (http://fontawesome.io) -* license: http://fontawesome.io/license/ -* -* Icons used to identify various websites are property of the respective websites. -*/ - -(function() { - -'use strict'; - -var $, $$, Anonymize, AntiAutoplay, ArchiveLink, Banner, Board, BoardConfig, CSS, Callbacks, Captcha, CatalogLinks, CatalogThread, CatalogThreadNative, Config, Connection, CopyTextLink, CrossOrigin, CustomCSS, DataBoard, DeleteLink, DownloadLink, Embedding, ExpandComment, ExpandThread, FappeTyme, Favicon, Fetcher, FileInfo, Filter, Flash, Fourchan, Gallery, Get, Header, IDColor, IDHighlight, IDPostCount, ImageCommon, ImageExpand, ImageHost, ImageHover, ImageLoader, Index, Keybinds, Linkify, Main, MarkNewIPs, Menu, Metadata, ModContact, Nav, NormalizeURL, Notice, PSA, PSAHiding, PassLink, PassMessage, Polyfill, Post, PostHiding, PostJumper, PostRedirect, PostSuccessful, QR, QuoteBacklink, QuoteCT, QuoteInline, QuoteOP, QuotePreview, QuoteStrikeThrough, QuoteThreading, QuoteYou, Quotify, RandomAccessList, Recursive, Redirect, RelativeDates, RemoveSpoilers, ReplyPruning, Report, ReportLink, RevealSpoilers, SW, Sauce, Settings, ShimSet, SimpleDict, Site, Test, Thread, ThreadHiding, ThreadLinks, ThreadStats, ThreadUpdater, ThreadWatcher, Time, Tinyboard, UI, Unread, UnreadIndex, Volume; - -var Conf, E, c, d, doc, docSet, g; - -Conf = Object.create(null); -c = console; -d = document; -doc = d.documentElement; - -// Workaround for userscript managers that run script before document.documentElement is set -docSet = function() { - return (doc = d.documentElement); -}; - -g = { - VERSION: '1.14.22.4', - NAMESPACE: '4chan X.', - sites: Object.create(null), - boards: Object.create(null) -}; - -E = (function() { - var fn, r, regex, str; - str = { - '&': '&', - "'": ''', - '"': '"', - '<': '<', - '>': '>' - }; - r = String.prototype.replace; - regex = /[&"'<>]/g; - fn = function(x) { - return str[x]; - }; - return function(text) { - return r.call(text, regex, fn); - }; -})(); - -E.cat = function(templates) { - var html, i, len; - html = ''; - for (i = 0, len = templates.length; i < len; i++) { - html += templates[i].innerHTML; - } - return html; -}; - -Config = (function() { - var Config; - - Config = { - main: { - 'Miscellaneous': { - 'Redirect to HTTPS': [true, 'Redirect to the HTTPS version of 4chan.'], - 'JSON Index': [true, 'Replace the original board index with one supporting searching, sorting, infinite scrolling, and a catalog mode.'], - 'Use 4chan X Catalog': [true, 'Link to 4chan X\'s catalog instead of the native 4chan one.', 1], - 'Index Refresh Notifications': [false, 'Show a notice at the top of the page when the index is refreshed.', 1], - 'Follow Cursor': [true, 'Image Hover and Quote Preview move with the mouse cursor.'], - 'Open Threads in New Tab': [false, 'Make links to threads in the index / 4chan X catalog open in a new tab.'], - 'External Catalog': [false, 'Link to external catalog instead of the internal one.'], - 'Catalog Links': [false, 'Add toggle link in header menu to turn Navigation links into links to each board\'s catalog.'], - 'Announcement Hiding': [true, 'Add button to hide 4chan announcements.'], - 'Desktop Notifications': [true, 'Enables desktop notifications across various 4chan X features.'], - '404 Redirect': [true, 'Redirect dead threads and images to the archives.'], - 'Archive Report': [true, 'Enable reporting posts to supported archives.'], - 'Exempt Archives from Encryption': [true, 'Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages.'], - 'Keybinds': [true, 'Bind actions to keyboard shortcuts.'], - 'Time Formatting': [true, 'Localize and format timestamps.'], - 'Relative Post Dates': [true, 'Display dates like "3 minutes ago". Tooltip shows the timestamp.'], - 'Relative Date Title': [true, 'Show Relative Post Date only when hovering over dates.', 1], - 'Comment Expansion': [true, 'Expand comments that are too long to display on the index. Not applicable with JSON Index.'], - 'File Info Formatting': [true, 'Reformat the file information.'], - 'Thread Expansion': [true, 'Add buttons to expand threads.'], - 'Index Navigation': [false, 'Add buttons to navigate between threads.'], - 'Reply Navigation': [false, 'Add buttons to navigate to top / bottom of thread.'], - 'Unique ID and Capcode Navigation': [false, 'Add buttons to navigate to posts having the same unique ID or capcode.'], - 'Custom Board Titles': [true, 'Allow editing of the board title and subtitle by ctrl/\u2318+clicking them.'], - 'Persistent Custom Board Titles': [false, 'Force custom board titles to be persistent, even if the board titles are updated.', 1], - 'Show Updated Notifications': [true, 'Show notifications when 4chan X is successfully updated.'], - 'Color User IDs': [true, 'Assign unique colors to user IDs on boards that use them'], - 'Count Posts by ID': [true, 'Display number of posts in the thread when hovering over an ID.'], - 'Remove Spoilers': [false, 'Remove all spoilers in text.'], - 'Reveal Spoilers': [false, 'Indicate spoilers if Remove Spoilers is enabled, or make the text appear hovered if Remove Spoiler is disabled.'], - 'Normalize URL': [true, 'Rewrite the URL of the current page, removing slugs and excess slashes, and changing /res/ to /thread/.'], - 'Work around CORB Bug': [true, 'Leave this checked until your garbage browser is fixed.'], - 'Disable Autoplaying Sounds': [false, 'Prevent sounds on the page from autoplaying.'], - 'Disable Native Extension': [true, '4chan X is NOT designed to work with the native extension.'], - 'Enable Native Flash Embedding': [true, 'Activate the native extension\'s Flash embedding if the native extension is disabled.'] - }, - 'Linkification': { - 'Linkify': [true, 'Convert text into links where applicable.'], - 'Link Title': [true, 'Replace the link of a supported site with its actual title.', 1], - 'Cover Preview': [true, 'Show preview of supported links on hover.', 1], - 'Embedding': [true, 'Embed supported services. Note: Some services don\'t work on HTTPS.', 1], - 'Auto-embed': [false, 'Auto-embed Linkify Embeds.', 2], - 'Floating Embeds': [false, 'Embed content in a frame that remains in place when the page is scrolled.', 2] - }, - 'Filtering': { - 'Anonymize': [false, 'Make everyone Anonymous.'], - 'Filter': [true, 'Self-moderation placebo.'], - 'Filtered Backlinks': [false, 'When enabled, shows backlinks to filtered posts with a line-through decoration. Otherwise, hides the backlinks.', 1], - 'Filter in Native Catalog': [true, 'Apply 4chan X filters in native catalog.', 1], - 'MD5 Quick Filter Notifications': [true, 'Show notification when quick filtering MD5s using the button or keybind.', 1], - 'Recursive Hiding': [true, 'Hide replies of hidden posts, recursively.'], - 'Thread Hiding Buttons': [true, 'Add buttons to hide entire threads.'], - 'Reply Hiding Buttons': [true, 'Add buttons to hide single replies.'], - 'Stubs': [true, 'Show stubs of hidden threads / replies.'] - }, - 'Images and Videos': { - 'Image Expansion': [true, 'Expand images / videos.'], - 'Image Hover': [true, 'Show full image / video on mouseover.'], - 'Image Hover in Catalog': [true, 'Show full image / video on mouseover in 4chan X catalog.'], - 'Gallery': [true, 'Adds a simple and cute image gallery. Has more options in the gallery menu.'], - 'Fullscreen Gallery': [false, 'Open gallery in fullscreen mode.', 1], - 'PDF in Gallery': [false, 'Show PDF files in gallery.', 1], - 'Sauce': [true, 'Add sauce links to images.'], - 'WEBM Metadata': [true, 'Add link to fetch title metadata from webm videos.'], - 'Reveal Spoiler Thumbnails': [false, 'Replace spoiler thumbnails with the original image.'], - 'Replace GIF': [false, 'Replace gif thumbnails with the actual image.'], - 'Replace JPG': [false, 'Replace jpg thumbnails with the actual image.'], - 'Replace PNG': [false, 'Replace png thumbnails with the actual image.'], - 'Replace WEBM': [false, 'Replace webm, mp4, and ogv thumbnails with the actual video. Probably will degrade browser performance ;)'], - 'Image Prefetching': [true, 'Add a shortcut icon to the header to turn on image preloading.'], - 'Fappe Tyme': [true, 'Hide posts without images when header menu item is checked. *hint* *hint*'], - 'Werk Tyme': [true, 'Hide all post images when header menu item is checked.'], - 'Autoplay': [true, 'Videos begin playing immediately when opened.'], - 'Restart when Opened': [false, 'Restart GIFs and WebMs when you hover over or expand them.'], - 'Show Controls': [true, 'Show controls on videos expanded inline.'], - 'Click Passthrough': [false, 'Clicks on videos trigger your browser\'s default behavior. Videos can be contracted with button / dragging to the left.', 1], - 'Allow Sound': [true, 'Open videos with the sound unmuted.'], - 'Mouse Wheel Volume': [true, 'Adjust volume of videos with the mouse wheel over the thumbnail/filename/gallery.'], - 'Loop in New Tab': [true, 'Loop videos opened in their own tabs.'], - 'Volume in New Tab': [true, 'Apply 4chan X mute and volume settings to videos opened in their own tabs.'] - }, - 'Menu': { - 'Menu': [true, 'Add a drop-down menu to posts.'], - 'Report Link': [true, 'Add a report link to the menu.', 1], - 'Copy Text Link': [true, 'Add a link to copy the post\'s text.', 1], - 'Thread Hiding Link': [true, 'Add a link to hide entire threads.', 1], - 'Reply Hiding Link': [true, 'Add a link to hide single replies.', 1], - 'Delete Link': [true, 'Add post and image deletion links to the menu.', 1], - 'Archive Link': [true, 'Add an archive link to the menu.', 1], - 'Edit Link': [true, 'Add a link to edit the image in Tegaki, /i/\'s painting program. Requires Quick Reply.', 1], - 'Download Link': [false, 'Add a download with original filename link to the menu.', 1] - }, - 'Monitoring': { - 'Thread Updater': [true, 'Fetch and insert new replies. Has more options in the header menu and the "Advanced" tab.'], - 'Unread Count': [true, 'Show the unread posts count in the tab title.'], - 'Quoted Title': [false, 'Change the page title to reflect you\'ve been quoted.', 1], - 'Hide Unread Count at (0)': [false, 'Hide the unread posts count in the tab title when it reaches 0.', 1], - 'Unread Favicon': [true, 'Show a different favicon when there are unread posts.'], - 'Unread Line': [true, 'Show a line to distinguish read posts from unread ones.'], - 'Remember Last Read Post': [true, 'Remember how far you\'ve read after you close the thread.'], - 'Scroll to Last Read Post': [true, 'Scroll back to the last read post when reopening a thread.', 1], - 'Unread Line in Index': [false, 'Show a line between read and unread posts in threads in the index.', 1], - 'Remove Thread Excerpt': [false, 'Replace the excerpt of the thread in the tab title with the board title.'], - 'Thread Stats': [true, 'Display reply and image count.'], - 'IP Count in Stats': [true, 'Display the unique IP count in the thread stats.', 1], - 'Page Count in Stats': [true, 'Display the page count in the thread stats.', 1], - 'Updater and Stats in Header': [true, 'Places the thread updater and thread stats in the header instead of floating them.'], - 'Thread Watcher': [true, 'Bookmark threads. Has more options in the thread watcher menu.'], - 'Fixed Thread Watcher': [true, 'Makes the thread watcher scroll with the page.', 1], - 'Persistent Thread Watcher': [false, 'The thread watcher will be visible when the page is loaded.', 1], - 'Mark New IPs': [false, 'Label each post from a new IP with the thread\'s current IP count.'], - 'Reply Pruning': [true, 'Add option in header menu to hide old replies in long threads. Activated by default in stickies.'], - 'Prune All Threads': [false, 'Activate Reply Pruning by default in all threads.', 1] - }, - 'Posting and Captchas': { - 'Quick Reply': [true, 'All-in-one form to reply, create threads, automate dumping and more.'], - 'Persistent QR': [false, 'The Quick reply won\'t disappear after posting.', 1], - 'Auto Hide QR': [true, 'Automatically hide the quick reply when posting.', 2], - 'Open Post in New Tab': [true, 'Open new threads in a new tab, and open replies in a new tab if you\'re not already in the thread.', 1], - 'Remember QR Size': [false, 'Remember the size of the Quick reply.', 1], - 'Remember Spoiler': [false, 'Remember the spoiler state, instead of resetting after posting.', 1], - 'Randomize Filename': [false, 'Set the filename to a random timestamp within the past year. Disabled on /f/.', 1], - 'Show New Thread Option in Threads': [true, 'Show the option to post a new / different thread from inside a thread.', 1], - 'Show Upload Progress': [true, 'Track progress of file uploads as percentage in submit button.', 1], - 'Cooldown': [true, 'Indicate the remaining time before posting again.', 1], - 'Posting Success Notifications': [true, 'Show notifications on successful post creation or file uploading.', 1], - 'Auto-load captcha': [false, 'Automatically load the captcha in the QR even if your post is empty.', 1], - 'Post on Captcha Completion': [false, 'Submit the post immediately when the captcha is completed.', 1], - 'Force Noscript Captcha': [false, 'Use the non-Javascript fallback captcha even if Javascript is enabled.'], - 'Pass Link': [false, 'Add a 4chan Pass login link to the bottom of the page.'] - }, - 'Quote Links': { - 'Quote Backlinks': [true, 'Add quote backlinks.'], - 'OP Backlinks': [true, 'Add backlinks to the OP.', 1], - 'Bottom Backlinks': [false, 'Place backlinks at the bottom of posts.', 1], - 'Quote Inlining': [true, 'Inline quoted post on click.'], - 'Inline Cross-thread Quotes Only': [false, 'Don\'t inline quote links when the posts are visible in the thread.', 1], - 'Quote Hash Navigation': [false, 'Include an extra link after quotes for autoscrolling to quoted posts.', 1], - 'Forward Hiding': [true, 'Hide original posts of inlined backlinks.', 1], - 'Quote Previewing': [true, 'Show quoted post on hover.'], - 'Quote Highlighting': [true, 'Highlight the previewed post.', 1], - 'Resurrect Quotes': [true, 'Link dead quotes to the archives, and support inlining/previewing of archive links like quote links.'], - 'Remember Your Posts': [true, 'Remember your posting history.'], - 'Mark Quotes of You': [true, 'Add \'(You)\' to quotes linking to your posts.', 1], - 'Highlight Posts Quoting You': [true, 'Highlights any posts that contain a quote to your post.', 1], - 'Highlight Own Posts': [true, 'Highlights own posts.', 1], - 'Mark OP Quotes': [true, 'Add \'(OP)\' to OP quotes.'], - 'Mark Cross-thread Quotes': [true, 'Add \'(Cross-thread)\' to cross-threads quotes.'], - 'Quote Threading': [true, 'Add option in header menu to thread conversations.'] - } - }, - imageExpansion: { - 'Fit width': [true, ''], - 'Fit height': [false, ''], - 'Scroll into view': [true, 'Scroll down when expanding images to bring the full image into view.'], - 'Expand spoilers': [true, 'Expand all images along with spoilers.'], - 'Expand videos': [true, 'Expand all images also expands videos.'], - 'Expand from here': [false, 'Expand all images only from current position to thread end.'], - 'Expand thread only': [false, 'In index, expand all images only within the current thread.'], - 'Advance on contract': [false, 'Advance to next post when contracting an expanded image.'] - }, - gallery: { - 'Hide Thumbnails': [false], - 'Fit Width': [true], - 'Fit Height': [true], - 'Stretch to Fit': [false], - 'Scroll to Post': [true], - 'Slide Delay': [6.0] - }, - 'Default Volume': 1.0, - threadWatcher: { - 'Current Board': [false, 'Only show watched threads from the current board.'], - 'Auto Update Thread Watcher': [true, 'Periodically check status of watched threads.'], - 'Auto Watch': [true, 'Automatically watch threads you start.'], - 'Auto Watch Reply': [true, 'Automatically watch threads you reply to.'], - 'Auto Prune': [false, 'Automatically remove dead threads.'], - 'Show Page': [true, 'Show what page watched threads are on.'], - 'Show Unread Count': [true, 'Show number of unread posts in watched threads.'], - 'Show Site Prefix': [true, 'When multiple sites are shown in the thread watcher, add a prefix to board names to distinguish them.'], - 'Require OP Quote Link': [false, 'For purposes of thread watcher highlighting, only consider posts with a quote link to the OP as replies to the OP.'] - }, - filter: { - general: '', - postID: "# Highlight dubs on [s4s]:\n#/(\\d)\\1$/;highlight;top:no;boards:s4s", - name: "# Filter any namefags:\n#/^(?!Anonymous$)/", - uniqueID: "# Filter a specific ID:\n#/Txhvk1Tl/", - tripcode: "# Filter any tripfag\n#/^!/", - capcode: "# Set a custom class for mods:\n#/Mod$/;highlight:mod;op:yes\n# Set a custom class for admins:\n#/Admin$/;highlight:admin;op:yes", - pass: "# Filter anyone using since4pass:\n#/./", - email: '', - 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\n# Filter posts with 20 or more quote links:\n#/(?:>>\\d(?:(?!>>\\d)[^])*){20}/\n# Filter posts like T H I S / H / I / S:\n#/^>?\\s?\\w\\s?(\\w)\\s?(\\w)\\s?(\\w).*$[\\s>]+\\1[\\s>]+\\2[\\s>]+\\3/im", - flag: '', - filename: '', - dimensions: "# Highlight potential wallpapers:\n#/1920x1080/;op:yes;highlight;top:no;boards:w,wg", - filesize: '', - MD5: '' - }, - sauces: "# Known filename formats:\nhttps://www.pixiv.net/member_illust.php?mode=medium&illust_id=%$1;regexp:/^(\\d+)_p\\d+/\njavascript:void(open(\"https://www.deviantart.com/\"+%$1.replace(/_/g,\"-\")+\"/art/\"+parseInt(%$2,36)));regexp:/^\\w+_by_(\\w+)[_-]d([\\da-z]{6})\\b/\nhttps://imgur.com/%$1;regexp:/^(?![a-zA-Z][a-z]{6})(?![A-Z]{7})(?!\\d{7})([\\da-zA-Z]{7})(?: \\(\\d+\\))?\\.\\w+$/\nhttps://flickr.com/photo.gne?id=%$1;regexp:/^(\\d+)_[\\da-f]{10}(?:_\\w)*\\b/\nhttps://www.facebook.com/photo.php?fbid=%$1;regexp:/^\\d+_(\\d+)_\\d+_[no]\\b/\n\n# Reverse image search:\nhttps://www.google.com/searchbyimage?sbisrc=4chanx&image_url=%IMG&safe=off\nhttps://yandex.com/images/search?rpt=imageview&url=%IMG\n#//tineye.com/search?url=%IMG\n#//www.bing.com/images/search?q=imgurl:%IMG&view=detailv2&iss=sbi#enterInsights\n#https://lens.google.com/uploadbyurl?url=%IMG;text:lens\n\n# Specialized reverse image search:\n//iqdb.org/?url=%IMG\nhttps://trace.moe/?auto&url=%IMG;text:wait\n#//3d.iqdb.org/?url=%IMG\n#//saucenao.com/search.php?url=%IMG\n\n# \"View Same\" in archives:\nhttp://eye.swfchan.com/search/?q=%name;types:swf\n#https://desuarchive.org/_/search/image/%sMD5/\n#https://archive.4plebs.org/_/search/image/%sMD5/\n#https://boards.fireden.net/_/search/image/%sMD5/\n#https://foolz.fireden.net/_/search/image/%sMD5/\n\n# Other tools:\n#http://exif.regex.info/exif.cgi?imgurl=%URL\n#//imgops.com/start?url=%URL;types:gif,jpg,png\n#//www.gif-explode.com/%URL;types:gif", - FappeT: { - werk: false - }, - 'Custom CSS': true, - Index: { - 'Index Mode': 'paged', - 'Previous Index Mode': 'paged', - 'Index Size': 'small', - 'Show Replies': [true, 'Show replies in the index, and also in the catalog if "Catalog hover expand" is checked.'], - 'Catalog Hover Expand': [false, 'Expand the comment and show more details when you hover over a thread in the catalog.'], - 'Catalog Hover Toggle': [true, 'Turn "Catalog hover expand" on and off by clicking in the catalog.'], - 'Pin Watched Threads': [false, 'Move watched threads to the start of the index.'], - 'Anchor Hidden Threads': [true, 'Move hidden threads to the end of the index.'], - 'Refreshed Navigation': [false, 'Refresh index when navigating through pages.'] - }, - Header: { - 'Fixed Header': true, - 'Header auto-hide': false, - 'Header auto-hide on scroll': false, - 'Bottom Header': false, - 'Centered links': false, - 'Header catalog links': false, - 'Bottom Board List': true, - 'Shortcut Icons': true, - 'Custom Board Navigation': true - }, - archives: { - archiveLists: 'https://4chenz.github.io/archives.json/archives.json', - lastarchivecheck: 0, - archiveAutoUpdate: true - }, - externalCatalogURLs: "//catalog.neet.tv/%board/;boards:4chan.org:3,a,adv,an,asp,biz,c,cgl,ck,cm,co,diy,f,fa,fit,g,gd,his,i,int,jp,k,lgbt,lit,m,mlp,mu,n,news,o,out,p,po,pol,s4s,sci,sp,tg,toy,trv,tv,v,vg,vip,vp,vr,w,wg,wsg,wsr,x", - boardnav: "[ toggle-all ]\n[current-index-text:\"Index\"\ncurrent-catalog-text:\"Catalog\"\ncurrent-expired-text:\"Expired\"\ncurrent-archive-text:\"Archive\"]\n[external-text:\"FAQ\",\"https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions\"]", - QR: { - 'QR.personas': "#options:\"sage\";boards:jp;always", - sjisPreview: false - }, - jsWhitelist: 'http://s.4cdn.org\nhttps://s.4cdn.org\nhttp://www.google.com\nhttps://www.google.com\nhttps://www.gstatic.com\nhttp://cdn.mathjax.org\nhttps://cdn.mathjax.org\nhttps://cdnjs.cloudflare.com\nhttps://hcaptcha.com\nhttps://*.hcaptcha.com\n\'self\'\n\'unsafe-inline\'\n\'unsafe-eval\'', - captchaLanguage: '', - time: '%m/%d/%y(%a)%H:%M:%S', - timeLocale: '', - backlink: '>>%id', - pastedname: 'file', - fileInfo: '%l %d (%p%s, %r%g)', - favicon: 'ferongr', - usercss: "/* Board title rice */\ndiv.boardTitle {\n font-weight: 400 !important;\n}\n:root.yotsuba div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(100,0,0,0.6);\n}\n:root.yotsuba-b div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(105,10,15,0.6);\n}\n:root.photon div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(0,74,153,0.6);\n}\n:root.tomorrow div.boardTitle {\n font-family: sans-serif !important;\n text-shadow: 1px 1px 1px rgba(167,170,168,0.6);\n}\n", - hotkeys: { - 'Toggle board list': ['Ctrl+b', 'Toggle the full board list.'], - 'Toggle header': ['Shift+h', 'Toggle the auto-hide option of the header.'], - 'Open empty QR': ['q', 'Open QR without post number inserted.'], - 'Open QR': ['Shift+q', 'Open QR with post number inserted.'], - 'Open settings': ['Alt+o', 'Open Settings.'], - 'Close': ['Esc', 'Close dialogs or notifications.'], - 'Spoiler tags': ['Ctrl+s', 'Insert spoiler tags.'], - 'Code tags': ['Alt+c', 'Insert code tags.'], - 'Eqn tags': ['Alt+e', 'Insert eqn tags.'], - 'Math tags': ['Alt+m', 'Insert math tags.'], - 'SJIS tags': ['Alt+a', 'Insert SJIS tags.'], - 'Toggle sage': ['Alt+s', 'Toggle sage in options field.'], - 'Toggle Cooldown': ['Alt+Comma', 'Toggle custom cooldown timer.'], - 'Post from URL': ['Alt+l', 'Post from URL.'], - 'Add new post': ['Alt+n', 'Add new post to the QR dump list.'], - 'Submit QR': ['Ctrl+Enter', 'Submit post.'], - 'Watch': ['w', 'Watch thread.'], - 'Update': ['r', 'Update the thread / refresh the index.'], - 'Update thread watcher': ['Shift+r', 'Manually refresh thread watcher.'], - 'Toggle thread watcher': ['t', 'Toggle visibility of thread watcher.'], - 'Toggle threading': ['Shift+t', 'Toggle threading.'], - 'Mark thread read': ['Ctrl+0', 'Mark thread read from index (requires "Unread Line in Index").'], - 'Expand image': ['Shift+e', 'Expand selected image.'], - 'Expand images': ['e', 'Expand all images.'], - 'Open Gallery': ['g', 'Opens the gallery.'], - 'Next Gallery Image': ['Right', 'Go to the next image in gallery mode.'], - 'Previous Gallery Image': ['Left', 'Go to the previous image in gallery mode.'], - 'Advance Gallery': ['Enter', 'Go to next image or, if Autoplay is off, play video.'], - 'Pause': ['p', 'Pause/play videos in the gallery.'], - 'Slideshow': ['Ctrl+Right', 'Toggle the gallery slideshow mode.'], - 'Rotate image clockwise': ['Shift+Right', 'Rotate image clockwise in gallery.'], - 'Rotate image anticlockwise': ['Shift+Left', 'Rotate image anticlockwise in gallery.'], - 'Download Gallery Image': ['Shift+j', 'Download current image in gallery.'], - 'fappeTyme': ['f', 'Toggle Fappe Tyme.'], - 'werkTyme': ['Shift+w', 'Toggle Werk Tyme.'], - 'Front page': ['1', 'Jump to front page.'], - 'Open front page': ['Shift+1', 'Open front page in a new tab.'], - 'Next page': ['Ctrl+Right', 'Jump to the next page.'], - 'Previous page': ['Ctrl+Left', 'Jump to the previous page.'], - 'Paged mode': ['Alt+1', 'Open the index in paged mode.'], - 'Infinite scrolling mode': ['Alt+2', 'Open the index in infinite scrolling mode.'], - 'All pages mode': ['Alt+3', 'Open the index in all threads mode.'], - 'Open catalog': ['Shift+c', 'Open the catalog of the current board.'], - 'Search form': ['Ctrl+Alt+s', 'Focus the search field on the board index.'], - 'Cycle sort type': ['Alt+x', 'Cycle through index sort types.'], - 'Next thread': ['Ctrl+Down', 'See next thread.'], - 'Previous thread': ['Ctrl+Up', 'See previous thread.'], - 'Expand thread': ['Ctrl+e', 'Expand thread.'], - 'Open thread': ['o', 'Open thread in current tab.'], - 'Open thread tab': ['Shift+o', 'Open thread in new tab.'], - 'Next reply': ['j', 'Select next reply.'], - 'Previous reply': ['k', 'Select previous reply.'], - 'Deselect reply': ['Shift+d', 'Deselect reply.'], - 'Hide': ['x', 'Hide thread.'], - 'Quick Filter MD5': ['5', 'Add the MD5 of the selected image to the filter list.'], - 'Previous Post Quoting You': ['Alt+Up', 'Scroll to the previous post that quotes you.'], - 'Next Post Quoting You': ['Alt+Down', 'Scroll to the next post that quotes you.'] - }, - updater: { - checkbox: { - 'Beep': [false, 'Beep on new post to completely read thread.'], - 'Beep Quoting You': [false, 'Beep on new post quoting you.'], - 'Auto Scroll': [false, 'Scroll updated posts into view. Only enabled at bottom of page.'], - 'Bottom Scroll': [false, 'Always scroll to the bottom, not the first new post. Useful for event threads.'], - 'Scroll BG': [false, 'Auto-scroll background tabs.'], - 'Auto Update': [true, 'Automatically fetch new posts.'], - 'Optional Increase': [false, 'Increase the intervals between updates on threads without new posts.'] - }, - 'Interval': 5 - }, - customCooldown: 0, - customCooldownEnabled: true, - 'Thread Quotes': false, - 'Max Replies': 1000, - 'Autohiding Scrollbar': false, - position: { - 'embedding.position': 'top: 50px; right: 0px;', - 'thread-stats.position': 'bottom: 0px; right: 0px;', - 'updater.position': 'bottom: 0px; left: 0px;', - 'thread-watcher.position': 'top: 50px; left: 0px;', - 'qr.position': 'top: 50px; right: 0px;' - }, - fourchanImageHost: 'i.4cdn.org', - hiddenPSAList: [{}], - knownBanners: '0.jpg,1.jpg,2.jpg,4.jpg,6.jpg,7.jpg,8.jpg,9.jpg,10.jpg,11.jpg,12.jpg,13.jpg,14.jpg,16.jpg,17.jpg,18.jpg,19.jpg,20.jpg,21.jpg,22.jpg,24.jpg,25.jpg,26.jpg,28.jpg,29.jpg,33.jpg,38.jpg,39.jpg,43.jpg,44.jpg,45.jpg,46.jpg,47.jpg,52.jpg,54.jpg,57.jpg,59.jpg,60.jpg,61.jpg,64.jpg,66.jpg,67.jpg,69.jpg,71.jpg,72.jpg,76.jpg,77.jpg,81.jpg,82.jpg,83.jpg,84.jpg,88.jpg,90.jpg,91.jpg,96.jpg,98.jpg,99.jpg,100.jpg,104.jpg,106.jpg,116.jpg,119.jpg,137.jpg,140.jpg,148.jpg,149.jpg,150.jpg,154.jpg,156.jpg,157.jpg,158.jpg,159.jpg,161.jpg,162.jpg,164.jpg,165.jpg,166.jpg,167.jpg,168.jpg,169.jpg,170.jpg,171.jpg,172.jpg,173.jpg,174.jpg,175.jpg,176.jpg,178.jpg,179.jpg,180.jpg,181.jpg,182.jpg,183.jpg,186.jpg,189.jpg,190.jpg,192.jpg,193.jpg,194.jpg,197.jpg,198.jpg,200.jpg,201.jpg,202.jpg,203.jpg,205.jpg,206.jpg,207.jpg,208.jpg,210.jpg,213.jpg,214.jpg,215.jpg,216.jpg,218.jpg,219.jpg,220.jpg,221.jpg,222.jpg,223.jpg,224.jpg,227.jpg,0.png,1.png,2.png,3.png,5.png,6.png,9.png,10.png,11.png,12.png,14.png,16.png,19.png,20.png,21.png,22.png,23.png,24.png,26.png,27.png,28.png,29.png,30.png,31.png,32.png,33.png,34.png,37.png,39.png,40.png,41.png,42.png,43.png,44.png,45.png,48.png,49.png,50.png,51.png,52.png,53.png,57.png,58.png,59.png,64.png,66.png,67.png,68.png,69.png,70.png,71.png,72.png,76.png,78.png,79.png,81.png,82.png,85.png,86.png,87.png,89.png,95.png,98.png,100.png,101.png,102.png,105.png,106.png,107.png,109.png,110.png,111.png,112.png,113.png,114.png,115.png,116.png,118.png,119.png,120.png,121.png,122.png,123.png,126.png,128.png,130.png,134.png,136.png,138.png,139.png,140.png,142.png,145.png,146.png,149.png,150.png,151.png,152.png,153.png,154.png,155.png,156.png,157.png,158.png,159.png,160.png,163.png,164.png,165.png,166.png,167.png,168.png,169.png,170.png,171.png,172.png,173.png,174.png,178.png,179.png,180.png,181.png,182.png,184.png,186.png,188.png,190.png,192.png,193.png,194.png,195.png,196.png,197.png,198.png,200.png,202.png,203.png,205.png,206.png,207.png,209.png,212.png,213.png,214.png,216.png,217.png,218.png,219.png,220.png,221.png,222.png,223.png,224.png,225.png,226.png,229.png,231.png,232.png,233.png,234.png,235.png,237.png,238.png,239.png,240.png,241.png,242.png,244.png,245.png,246.png,247.png,248.png,249.png,250.png,253.png,254.png,255.png,256.png,257.png,258.png,259.png,260.png,262.png,268.png,0.gif,1.gif,2.gif,3.gif,4.gif,5.gif,6.gif,7.gif,8.gif,9.gif,10.gif,12.gif,13.gif,14.gif,15.gif,16.gif,18.gif,19.gif,20.gif,21.gif,22.gif,23.gif,24.gif,28.gif,29.gif,30.gif,33.gif,34.gif,35.gif,36.gif,37.gif,39.gif,40.gif,42.gif,44.gif,45.gif,46.gif,48.gif,50.gif,52.gif,54.gif,55.gif,57.gif,58.gif,59.gif,60.gif,61.gif,63.gif,64.gif,66.gif,67.gif,68.gif,69.gif,70.gif,72.gif,73.gif,75.gif,76.gif,77.gif,78.gif,80.gif,81.gif,82.gif,83.gif,86.gif,87.gif,88.gif,92.gif,93.gif,94.gif,95.gif,96.gif,97.gif,98.gif,99.gif,100.gif,101.gif,102.gif,103.gif,104.gif,105.gif,106.gif,108.gif,109.gif,110.gif,111.gif,112.gif,113.gif,115.gif,116.gif,117.gif,118.gif,119.gif,120.gif,122.gif,123.gif,124.gif,127.gif,129.gif,130.gif,131.gif,134.gif,135.gif,136.gif,138.gif,139.gif,141.gif,144.gif,146.gif,148.gif,149.gif,153.gif,154.gif,155.gif,157.gif,158.gif,159.gif,160.gif,161.gif,162.gif,164.gif,166.gif,167.gif,168.gif,169.gif,170.gif,171.gif,172.gif,173.gif,174.gif,175.gif,176.gif,177.gif,178.gif,181.gif,182.gif,183.gif,185.gif,186.gif,187.gif,188.gif,189.gif,190.gif,191.gif,192.gif,193.gif,195.gif,196.gif,197.gif,200.gif,201.gif,202.gif,203.gif,204.gif,205.gif,206.gif,207.gif,208.gif,209.gif,210.gif,211.gif,212.gif,213.gif,214.gif,215.gif,216.gif,217.gif,219.gif,220.gif,221.gif,222.gif,224.gif,225.gif,226.gif,227.gif,228.gif,230.gif,232.gif,233.gif,234.gif,235.gif,238.gif,240.gif,241.gif,243.gif,244.gif,245.gif,246.gif,247.gif,249.gif,250.gif,251.gif,253.gif', - passMessageClosed: false, - 'Prerequest Captcha': false, - 'PSAseen': [[]] - }; - - return Config; - -}).call(this); - -CSS = { - -boards: -"/*!\n\ - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n\ - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n\ - */\n\ -@font-face {\n\ - font-family: FontAwesome;\n\ - src: url('data:application/font-woff;base64,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') format('woff');\n\ - font-weight: 400;\n\ - font-style: normal;\n\ -}\n\ -.fa-glass:before {content: \"\\f000\";}\n\ -.fa-music:before {content: \"\\f001\";}\n\ -.fa-search:before {content: \"\\f002\";}\n\ -.fa-envelope-o:before {content: \"\\f003\";}\n\ -.fa-heart:before {content: \"\\f004\";}\n\ -.fa-star:before {content: \"\\f005\";}\n\ -.fa-star-o:before {content: \"\\f006\";}\n\ -.fa-user:before {content: \"\\f007\";}\n\ -.fa-film:before {content: \"\\f008\";}\n\ -.fa-th-large:before {content: \"\\f009\";}\n\ -.fa-th:before {content: \"\\f00a\";}\n\ -.fa-th-list:before {content: \"\\f00b\";}\n\ -.fa-check:before {content: \"\\f00c\";}\n\ -.fa-remove:before, .fa-close:before, .fa-times:before {content: \"\\f00d\";}\n\ -.fa-search-plus:before {content: \"\\f00e\";}\n\ -.fa-search-minus:before {content: \"\\f010\";}\n\ -.fa-power-off:before {content: \"\\f011\";}\n\ -.fa-signal:before {content: \"\\f012\";}\n\ -.fa-gear:before, .fa-cog:before {content: \"\\f013\";}\n\ -.fa-trash-o:before {content: \"\\f014\";}\n\ -.fa-home:before {content: \"\\f015\";}\n\ -.fa-file-o:before {content: \"\\f016\";}\n\ -.fa-clock-o:before {content: \"\\f017\";}\n\ -.fa-road:before {content: \"\\f018\";}\n\ -.fa-download:before {content: \"\\f019\";}\n\ -.fa-arrow-circle-o-down:before {content: \"\\f01a\";}\n\ -.fa-arrow-circle-o-up:before {content: \"\\f01b\";}\n\ -.fa-inbox:before {content: \"\\f01c\";}\n\ -.fa-play-circle-o:before {content: \"\\f01d\";}\n\ -.fa-rotate-right:before, .fa-repeat:before {content: \"\\f01e\";}\n\ -.fa-refresh:before {content: \"\\f021\";}\n\ -.fa-list-alt:before {content: \"\\f022\";}\n\ -.fa-lock:before {content: \"\\f023\";}\n\ -.fa-flag:before {content: \"\\f024\";}\n\ -.fa-headphones:before {content: \"\\f025\";}\n\ -.fa-volume-off:before {content: \"\\f026\";}\n\ -.fa-volume-down:before {content: \"\\f027\";}\n\ -.fa-volume-up:before {content: \"\\f028\";}\n\ -.fa-qrcode:before {content: \"\\f029\";}\n\ -.fa-barcode:before {content: \"\\f02a\";}\n\ -.fa-tag:before {content: \"\\f02b\";}\n\ -.fa-tags:before {content: \"\\f02c\";}\n\ -.fa-book:before {content: \"\\f02d\";}\n\ -.fa-bookmark:before {content: \"\\f02e\";}\n\ -.fa-print:before {content: \"\\f02f\";}\n\ -.fa-camera:before {content: \"\\f030\";}\n\ -.fa-font:before {content: \"\\f031\";}\n\ -.fa-bold:before {content: \"\\f032\";}\n\ -.fa-italic:before {content: \"\\f033\";}\n\ -.fa-text-height:before {content: \"\\f034\";}\n\ -.fa-text-width:before {content: \"\\f035\";}\n\ -.fa-align-left:before {content: \"\\f036\";}\n\ -.fa-align-center:before {content: \"\\f037\";}\n\ -.fa-align-right:before {content: \"\\f038\";}\n\ -.fa-align-justify:before {content: \"\\f039\";}\n\ -.fa-list:before {content: \"\\f03a\";}\n\ -.fa-dedent:before, .fa-outdent:before {content: \"\\f03b\";}\n\ -.fa-indent:before {content: \"\\f03c\";}\n\ -.fa-video-camera:before {content: \"\\f03d\";}\n\ -.fa-photo:before, .fa-image:before, .fa-picture-o:before {content: \"\\f03e\";}\n\ -.fa-pencil:before {content: \"\\f040\";}\n\ -.fa-map-marker:before {content: \"\\f041\";}\n\ -.fa-adjust:before {content: \"\\f042\";}\n\ -.fa-tint:before {content: \"\\f043\";}\n\ -.fa-edit:before, .fa-pencil-square-o:before {content: \"\\f044\";}\n\ -.fa-share-square-o:before {content: \"\\f045\";}\n\ -.fa-check-square-o:before {content: \"\\f046\";}\n\ -.fa-arrows:before {content: \"\\f047\";}\n\ -.fa-step-backward:before {content: \"\\f048\";}\n\ -.fa-fast-backward:before {content: \"\\f049\";}\n\ -.fa-backward:before {content: \"\\f04a\";}\n\ -.fa-play:before {content: \"\\f04b\";}\n\ -.fa-pause:before {content: \"\\f04c\";}\n\ -.fa-stop:before {content: \"\\f04d\";}\n\ -.fa-forward:before {content: \"\\f04e\";}\n\ -.fa-fast-forward:before {content: \"\\f050\";}\n\ -.fa-step-forward:before {content: \"\\f051\";}\n\ -.fa-eject:before {content: \"\\f052\";}\n\ -.fa-chevron-left:before {content: \"\\f053\";}\n\ -.fa-chevron-right:before {content: \"\\f054\";}\n\ -.fa-plus-circle:before {content: \"\\f055\";}\n\ -.fa-minus-circle:before {content: \"\\f056\";}\n\ -.fa-times-circle:before {content: \"\\f057\";}\n\ -.fa-check-circle:before {content: \"\\f058\";}\n\ -.fa-question-circle:before {content: \"\\f059\";}\n\ -.fa-info-circle:before {content: \"\\f05a\";}\n\ -.fa-crosshairs:before {content: \"\\f05b\";}\n\ -.fa-times-circle-o:before {content: \"\\f05c\";}\n\ -.fa-check-circle-o:before {content: \"\\f05d\";}\n\ -.fa-ban:before {content: \"\\f05e\";}\n\ -.fa-arrow-left:before {content: \"\\f060\";}\n\ -.fa-arrow-right:before {content: \"\\f061\";}\n\ -.fa-arrow-up:before {content: \"\\f062\";}\n\ -.fa-arrow-down:before {content: \"\\f063\";}\n\ -.fa-mail-forward:before, .fa-share:before {content: \"\\f064\";}\n\ -.fa-expand:before {content: \"\\f065\";}\n\ -.fa-compress:before {content: \"\\f066\";}\n\ -.fa-plus:before {content: \"\\f067\";}\n\ -.fa-minus:before {content: \"\\f068\";}\n\ -.fa-asterisk:before {content: \"\\f069\";}\n\ -.fa-exclamation-circle:before {content: \"\\f06a\";}\n\ -.fa-gift:before {content: \"\\f06b\";}\n\ -.fa-leaf:before {content: \"\\f06c\";}\n\ -.fa-fire:before {content: \"\\f06d\";}\n\ -.fa-eye:before {content: \"\\f06e\";}\n\ -.fa-eye-slash:before {content: \"\\f070\";}\n\ -.fa-warning:before, .fa-exclamation-triangle:before {content: \"\\f071\";}\n\ -.fa-plane:before {content: \"\\f072\";}\n\ -.fa-calendar:before {content: \"\\f073\";}\n\ -.fa-random:before {content: \"\\f074\";}\n\ -.fa-comment:before {content: \"\\f075\";}\n\ -.fa-magnet:before {content: \"\\f076\";}\n\ -.fa-chevron-up:before {content: \"\\f077\";}\n\ -.fa-chevron-down:before {content: \"\\f078\";}\n\ -.fa-retweet:before {content: \"\\f079\";}\n\ -.fa-shopping-cart:before {content: \"\\f07a\";}\n\ -.fa-folder:before {content: \"\\f07b\";}\n\ -.fa-folder-open:before {content: \"\\f07c\";}\n\ -.fa-arrows-v:before {content: \"\\f07d\";}\n\ -.fa-arrows-h:before {content: \"\\f07e\";}\n\ -.fa-bar-chart-o:before, .fa-bar-chart:before {content: \"\\f080\";}\n\ -.fa-twitter-square:before {content: \"\\f081\";}\n\ -.fa-facebook-square:before {content: \"\\f082\";}\n\ -.fa-camera-retro:before {content: \"\\f083\";}\n\ -.fa-key:before {content: \"\\f084\";}\n\ -.fa-gears:before, .fa-cogs:before {content: \"\\f085\";}\n\ -.fa-comments:before {content: \"\\f086\";}\n\ -.fa-thumbs-o-up:before {content: \"\\f087\";}\n\ -.fa-thumbs-o-down:before {content: \"\\f088\";}\n\ -.fa-star-half:before {content: \"\\f089\";}\n\ -.fa-heart-o:before {content: \"\\f08a\";}\n\ -.fa-sign-out:before {content: \"\\f08b\";}\n\ -.fa-linkedin-square:before {content: \"\\f08c\";}\n\ -.fa-thumb-tack:before {content: \"\\f08d\";}\n\ -.fa-external-link:before {content: \"\\f08e\";}\n\ -.fa-sign-in:before {content: \"\\f090\";}\n\ -.fa-trophy:before {content: \"\\f091\";}\n\ -.fa-github-square:before {content: \"\\f092\";}\n\ -.fa-upload:before {content: \"\\f093\";}\n\ -.fa-lemon-o:before {content: \"\\f094\";}\n\ -.fa-phone:before {content: \"\\f095\";}\n\ -.fa-square-o:before {content: \"\\f096\";}\n\ -.fa-bookmark-o:before {content: \"\\f097\";}\n\ -.fa-phone-square:before {content: \"\\f098\";}\n\ -.fa-twitter:before {content: \"\\f099\";}\n\ -.fa-facebook-f:before, .fa-facebook:before {content: \"\\f09a\";}\n\ -.fa-github:before {content: \"\\f09b\";}\n\ -.fa-unlock:before {content: \"\\f09c\";}\n\ -.fa-credit-card:before {content: \"\\f09d\";}\n\ -.fa-feed:before, .fa-rss:before {content: \"\\f09e\";}\n\ -.fa-hdd-o:before {content: \"\\f0a0\";}\n\ -.fa-bullhorn:before {content: \"\\f0a1\";}\n\ -.fa-bell:before {content: \"\\f0f3\";}\n\ -.fa-certificate:before {content: \"\\f0a3\";}\n\ -.fa-hand-o-right:before {content: \"\\f0a4\";}\n\ -.fa-hand-o-left:before {content: \"\\f0a5\";}\n\ -.fa-hand-o-up:before {content: \"\\f0a6\";}\n\ -.fa-hand-o-down:before {content: \"\\f0a7\";}\n\ -.fa-arrow-circle-left:before {content: \"\\f0a8\";}\n\ -.fa-arrow-circle-right:before {content: \"\\f0a9\";}\n\ -.fa-arrow-circle-up:before {content: \"\\f0aa\";}\n\ -.fa-arrow-circle-down:before {content: \"\\f0ab\";}\n\ -.fa-globe:before {content: \"\\f0ac\";}\n\ -.fa-wrench:before {content: \"\\f0ad\";}\n\ -.fa-tasks:before {content: \"\\f0ae\";}\n\ -.fa-filter:before {content: \"\\f0b0\";}\n\ -.fa-briefcase:before {content: \"\\f0b1\";}\n\ -.fa-arrows-alt:before {content: \"\\f0b2\";}\n\ -.fa-group:before, .fa-users:before {content: \"\\f0c0\";}\n\ -.fa-chain:before, .fa-link:before {content: \"\\f0c1\";}\n\ -.fa-cloud:before {content: \"\\f0c2\";}\n\ -.fa-flask:before {content: \"\\f0c3\";}\n\ -.fa-cut:before, .fa-scissors:before {content: \"\\f0c4\";}\n\ -.fa-copy:before, .fa-files-o:before {content: \"\\f0c5\";}\n\ -.fa-paperclip:before {content: \"\\f0c6\";}\n\ -.fa-save:before, .fa-floppy-o:before {content: \"\\f0c7\";}\n\ -.fa-square:before {content: \"\\f0c8\";}\n\ -.fa-navicon:before, .fa-reorder:before, .fa-bars:before {content: \"\\f0c9\";}\n\ -.fa-list-ul:before {content: \"\\f0ca\";}\n\ -.fa-list-ol:before {content: \"\\f0cb\";}\n\ -.fa-strikethrough:before {content: \"\\f0cc\";}\n\ -.fa-underline:before {content: \"\\f0cd\";}\n\ -.fa-table:before {content: \"\\f0ce\";}\n\ -.fa-magic:before {content: \"\\f0d0\";}\n\ -.fa-truck:before {content: \"\\f0d1\";}\n\ -.fa-pinterest:before {content: \"\\f0d2\";}\n\ -.fa-pinterest-square:before {content: \"\\f0d3\";}\n\ -.fa-google-plus-square:before {content: \"\\f0d4\";}\n\ -.fa-google-plus:before {content: \"\\f0d5\";}\n\ -.fa-money:before {content: \"\\f0d6\";}\n\ -.fa-caret-down:before {content: \"\\f0d7\";}\n\ -.fa-caret-up:before {content: \"\\f0d8\";}\n\ -.fa-caret-left:before {content: \"\\f0d9\";}\n\ -.fa-caret-right:before {content: \"\\f0da\";}\n\ -.fa-columns:before {content: \"\\f0db\";}\n\ -.fa-unsorted:before, .fa-sort:before {content: \"\\f0dc\";}\n\ -.fa-sort-down:before, .fa-sort-desc:before {content: \"\\f0dd\";}\n\ -.fa-sort-up:before, .fa-sort-asc:before {content: \"\\f0de\";}\n\ -.fa-envelope:before {content: \"\\f0e0\";}\n\ -.fa-linkedin:before {content: \"\\f0e1\";}\n\ -.fa-rotate-left:before, .fa-undo:before {content: \"\\f0e2\";}\n\ -.fa-legal:before, .fa-gavel:before {content: \"\\f0e3\";}\n\ -.fa-dashboard:before, .fa-tachometer:before {content: \"\\f0e4\";}\n\ -.fa-comment-o:before {content: \"\\f0e5\";}\n\ -.fa-comments-o:before {content: \"\\f0e6\";}\n\ -.fa-flash:before, .fa-bolt:before {content: \"\\f0e7\";}\n\ -.fa-sitemap:before {content: \"\\f0e8\";}\n\ -.fa-umbrella:before {content: \"\\f0e9\";}\n\ -.fa-paste:before, .fa-clipboard:before {content: \"\\f0ea\";}\n\ -.fa-lightbulb-o:before {content: \"\\f0eb\";}\n\ -.fa-exchange:before {content: \"\\f0ec\";}\n\ -.fa-cloud-download:before {content: \"\\f0ed\";}\n\ -.fa-cloud-upload:before {content: \"\\f0ee\";}\n\ -.fa-user-md:before {content: \"\\f0f0\";}\n\ -.fa-stethoscope:before {content: \"\\f0f1\";}\n\ -.fa-suitcase:before {content: \"\\f0f2\";}\n\ -.fa-bell-o:before {content: \"\\f0a2\";}\n\ -.fa-coffee:before {content: \"\\f0f4\";}\n\ -.fa-cutlery:before {content: \"\\f0f5\";}\n\ -.fa-file-text-o:before {content: \"\\f0f6\";}\n\ -.fa-building-o:before {content: \"\\f0f7\";}\n\ -.fa-hospital-o:before {content: \"\\f0f8\";}\n\ -.fa-ambulance:before {content: \"\\f0f9\";}\n\ -.fa-medkit:before {content: \"\\f0fa\";}\n\ -.fa-fighter-jet:before {content: \"\\f0fb\";}\n\ -.fa-beer:before {content: \"\\f0fc\";}\n\ -.fa-h-square:before {content: \"\\f0fd\";}\n\ -.fa-plus-square:before {content: \"\\f0fe\";}\n\ -.fa-angle-double-left:before {content: \"\\f100\";}\n\ -.fa-angle-double-right:before {content: \"\\f101\";}\n\ -.fa-angle-double-up:before {content: \"\\f102\";}\n\ -.fa-angle-double-down:before {content: \"\\f103\";}\n\ -.fa-angle-left:before {content: \"\\f104\";}\n\ -.fa-angle-right:before {content: \"\\f105\";}\n\ -.fa-angle-up:before {content: \"\\f106\";}\n\ -.fa-angle-down:before {content: \"\\f107\";}\n\ -.fa-desktop:before {content: \"\\f108\";}\n\ -.fa-laptop:before {content: \"\\f109\";}\n\ -.fa-tablet:before {content: \"\\f10a\";}\n\ -.fa-mobile-phone:before, .fa-mobile:before {content: \"\\f10b\";}\n\ -.fa-circle-o:before {content: \"\\f10c\";}\n\ -.fa-quote-left:before {content: \"\\f10d\";}\n\ -.fa-quote-right:before {content: \"\\f10e\";}\n\ -.fa-spinner:before {content: \"\\f110\";}\n\ -.fa-circle:before {content: \"\\f111\";}\n\ -.fa-mail-reply:before, .fa-reply:before {content: \"\\f112\";}\n\ -.fa-github-alt:before {content: \"\\f113\";}\n\ -.fa-folder-o:before {content: \"\\f114\";}\n\ -.fa-folder-open-o:before {content: \"\\f115\";}\n\ -.fa-smile-o:before {content: \"\\f118\";}\n\ -.fa-frown-o:before {content: \"\\f119\";}\n\ -.fa-meh-o:before {content: \"\\f11a\";}\n\ -.fa-gamepad:before {content: \"\\f11b\";}\n\ -.fa-keyboard-o:before {content: \"\\f11c\";}\n\ -.fa-flag-o:before {content: \"\\f11d\";}\n\ -.fa-flag-checkered:before {content: \"\\f11e\";}\n\ -.fa-terminal:before {content: \"\\f120\";}\n\ -.fa-code:before {content: \"\\f121\";}\n\ -.fa-mail-reply-all:before, .fa-reply-all:before {content: \"\\f122\";}\n\ -.fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before {content: \"\\f123\";}\n\ -.fa-location-arrow:before {content: \"\\f124\";}\n\ -.fa-crop:before {content: \"\\f125\";}\n\ -.fa-code-fork:before {content: \"\\f126\";}\n\ -.fa-unlink:before, .fa-chain-broken:before {content: \"\\f127\";}\n\ -.fa-question:before {content: \"\\f128\";}\n\ -.fa-info:before {content: \"\\f129\";}\n\ -.fa-exclamation:before {content: \"\\f12a\";}\n\ -.fa-superscript:before {content: \"\\f12b\";}\n\ -.fa-subscript:before {content: \"\\f12c\";}\n\ -.fa-eraser:before {content: \"\\f12d\";}\n\ -.fa-puzzle-piece:before {content: \"\\f12e\";}\n\ -.fa-microphone:before {content: \"\\f130\";}\n\ -.fa-microphone-slash:before {content: \"\\f131\";}\n\ -.fa-shield:before {content: \"\\f132\";}\n\ -.fa-calendar-o:before {content: \"\\f133\";}\n\ -.fa-fire-extinguisher:before {content: \"\\f134\";}\n\ -.fa-rocket:before {content: \"\\f135\";}\n\ -.fa-maxcdn:before {content: \"\\f136\";}\n\ -.fa-chevron-circle-left:before {content: \"\\f137\";}\n\ -.fa-chevron-circle-right:before {content: \"\\f138\";}\n\ -.fa-chevron-circle-up:before {content: \"\\f139\";}\n\ -.fa-chevron-circle-down:before {content: \"\\f13a\";}\n\ -.fa-html5:before {content: \"\\f13b\";}\n\ -.fa-css3:before {content: \"\\f13c\";}\n\ -.fa-anchor:before {content: \"\\f13d\";}\n\ -.fa-unlock-alt:before {content: \"\\f13e\";}\n\ -.fa-bullseye:before {content: \"\\f140\";}\n\ -.fa-ellipsis-h:before {content: \"\\f141\";}\n\ -.fa-ellipsis-v:before {content: \"\\f142\";}\n\ -.fa-rss-square:before {content: \"\\f143\";}\n\ -.fa-play-circle:before {content: \"\\f144\";}\n\ -.fa-ticket:before {content: \"\\f145\";}\n\ -.fa-minus-square:before {content: \"\\f146\";}\n\ -.fa-minus-square-o:before {content: \"\\f147\";}\n\ -.fa-level-up:before {content: \"\\f148\";}\n\ -.fa-level-down:before {content: \"\\f149\";}\n\ -.fa-check-square:before {content: \"\\f14a\";}\n\ -.fa-pencil-square:before {content: \"\\f14b\";}\n\ -.fa-external-link-square:before {content: \"\\f14c\";}\n\ -.fa-share-square:before {content: \"\\f14d\";}\n\ -.fa-compass:before {content: \"\\f14e\";}\n\ -.fa-toggle-down:before, .fa-caret-square-o-down:before {content: \"\\f150\";}\n\ -.fa-toggle-up:before, .fa-caret-square-o-up:before {content: \"\\f151\";}\n\ -.fa-toggle-right:before, .fa-caret-square-o-right:before {content: \"\\f152\";}\n\ -.fa-euro:before, .fa-eur:before {content: \"\\f153\";}\n\ -.fa-gbp:before {content: \"\\f154\";}\n\ -.fa-dollar:before, .fa-usd:before {content: \"\\f155\";}\n\ -.fa-rupee:before, .fa-inr:before {content: \"\\f156\";}\n\ -.fa-cny:before, .fa-rmb:before, .fa-yen:before, .fa-jpy:before {content: \"\\f157\";}\n\ -.fa-ruble:before, .fa-rouble:before, .fa-rub:before {content: \"\\f158\";}\n\ -.fa-won:before, .fa-krw:before {content: \"\\f159\";}\n\ -.fa-bitcoin:before, .fa-btc:before {content: \"\\f15a\";}\n\ -.fa-file:before {content: \"\\f15b\";}\n\ -.fa-file-text:before {content: \"\\f15c\";}\n\ -.fa-sort-alpha-asc:before {content: \"\\f15d\";}\n\ -.fa-sort-alpha-desc:before {content: \"\\f15e\";}\n\ -.fa-sort-amount-asc:before {content: \"\\f160\";}\n\ -.fa-sort-amount-desc:before {content: \"\\f161\";}\n\ -.fa-sort-numeric-asc:before {content: \"\\f162\";}\n\ -.fa-sort-numeric-desc:before {content: \"\\f163\";}\n\ -.fa-thumbs-up:before {content: \"\\f164\";}\n\ -.fa-thumbs-down:before {content: \"\\f165\";}\n\ -.fa-youtube-square:before {content: \"\\f166\";}\n\ -.fa-youtube:before {content: \"\\f167\";}\n\ -.fa-xing:before {content: \"\\f168\";}\n\ -.fa-xing-square:before {content: \"\\f169\";}\n\ -.fa-youtube-play:before {content: \"\\f16a\";}\n\ -.fa-dropbox:before {content: \"\\f16b\";}\n\ -.fa-stack-overflow:before {content: \"\\f16c\";}\n\ -.fa-instagram:before {content: \"\\f16d\";}\n\ -.fa-flickr:before {content: \"\\f16e\";}\n\ -.fa-adn:before {content: \"\\f170\";}\n\ -.fa-bitbucket:before {content: \"\\f171\";}\n\ -.fa-bitbucket-square:before {content: \"\\f172\";}\n\ -.fa-tumblr:before {content: \"\\f173\";}\n\ -.fa-tumblr-square:before {content: \"\\f174\";}\n\ -.fa-long-arrow-down:before {content: \"\\f175\";}\n\ -.fa-long-arrow-up:before {content: \"\\f176\";}\n\ -.fa-long-arrow-left:before {content: \"\\f177\";}\n\ -.fa-long-arrow-right:before {content: \"\\f178\";}\n\ -.fa-apple:before {content: \"\\f179\";}\n\ -.fa-windows:before {content: \"\\f17a\";}\n\ -.fa-android:before {content: \"\\f17b\";}\n\ -.fa-linux:before {content: \"\\f17c\";}\n\ -.fa-dribbble:before {content: \"\\f17d\";}\n\ -.fa-skype:before {content: \"\\f17e\";}\n\ -.fa-foursquare:before {content: \"\\f180\";}\n\ -.fa-trello:before {content: \"\\f181\";}\n\ -.fa-female:before {content: \"\\f182\";}\n\ -.fa-male:before {content: \"\\f183\";}\n\ -.fa-gittip:before, .fa-gratipay:before {content: \"\\f184\";}\n\ -.fa-sun-o:before {content: \"\\f185\";}\n\ -.fa-moon-o:before {content: \"\\f186\";}\n\ -.fa-archive:before {content: \"\\f187\";}\n\ -.fa-bug:before {content: \"\\f188\";}\n\ -.fa-vk:before {content: \"\\f189\";}\n\ -.fa-weibo:before {content: \"\\f18a\";}\n\ -.fa-renren:before {content: \"\\f18b\";}\n\ -.fa-pagelines:before {content: \"\\f18c\";}\n\ -.fa-stack-exchange:before {content: \"\\f18d\";}\n\ -.fa-arrow-circle-o-right:before {content: \"\\f18e\";}\n\ -.fa-arrow-circle-o-left:before {content: \"\\f190\";}\n\ -.fa-toggle-left:before, .fa-caret-square-o-left:before {content: \"\\f191\";}\n\ -.fa-dot-circle-o:before {content: \"\\f192\";}\n\ -.fa-wheelchair:before {content: \"\\f193\";}\n\ -.fa-vimeo-square:before {content: \"\\f194\";}\n\ -.fa-turkish-lira:before, .fa-try:before {content: \"\\f195\";}\n\ -.fa-plus-square-o:before {content: \"\\f196\";}\n\ -.fa-space-shuttle:before {content: \"\\f197\";}\n\ -.fa-slack:before {content: \"\\f198\";}\n\ -.fa-envelope-square:before {content: \"\\f199\";}\n\ -.fa-wordpress:before {content: \"\\f19a\";}\n\ -.fa-openid:before {content: \"\\f19b\";}\n\ -.fa-institution:before, .fa-bank:before, .fa-university:before {content: \"\\f19c\";}\n\ -.fa-mortar-board:before, .fa-graduation-cap:before {content: \"\\f19d\";}\n\ -.fa-yahoo:before {content: \"\\f19e\";}\n\ -.fa-google:before {content: \"\\f1a0\";}\n\ -.fa-reddit:before {content: \"\\f1a1\";}\n\ -.fa-reddit-square:before {content: \"\\f1a2\";}\n\ -.fa-stumbleupon-circle:before {content: \"\\f1a3\";}\n\ -.fa-stumbleupon:before {content: \"\\f1a4\";}\n\ -.fa-delicious:before {content: \"\\f1a5\";}\n\ -.fa-digg:before {content: \"\\f1a6\";}\n\ -.fa-pied-piper-pp:before {content: \"\\f1a7\";}\n\ -.fa-pied-piper-alt:before {content: \"\\f1a8\";}\n\ -.fa-drupal:before {content: \"\\f1a9\";}\n\ -.fa-joomla:before {content: \"\\f1aa\";}\n\ -.fa-language:before {content: \"\\f1ab\";}\n\ -.fa-fax:before {content: \"\\f1ac\";}\n\ -.fa-building:before {content: \"\\f1ad\";}\n\ -.fa-child:before {content: \"\\f1ae\";}\n\ -.fa-paw:before {content: \"\\f1b0\";}\n\ -.fa-spoon:before {content: \"\\f1b1\";}\n\ -.fa-cube:before {content: \"\\f1b2\";}\n\ -.fa-cubes:before {content: \"\\f1b3\";}\n\ -.fa-behance:before {content: \"\\f1b4\";}\n\ -.fa-behance-square:before {content: \"\\f1b5\";}\n\ -.fa-steam:before {content: \"\\f1b6\";}\n\ -.fa-steam-square:before {content: \"\\f1b7\";}\n\ -.fa-recycle:before {content: \"\\f1b8\";}\n\ -.fa-automobile:before, .fa-car:before {content: \"\\f1b9\";}\n\ -.fa-cab:before, .fa-taxi:before {content: \"\\f1ba\";}\n\ -.fa-tree:before {content: \"\\f1bb\";}\n\ -.fa-spotify:before {content: \"\\f1bc\";}\n\ -.fa-deviantart:before {content: \"\\f1bd\";}\n\ -.fa-soundcloud:before {content: \"\\f1be\";}\n\ -.fa-database:before {content: \"\\f1c0\";}\n\ -.fa-file-pdf-o:before {content: \"\\f1c1\";}\n\ -.fa-file-word-o:before {content: \"\\f1c2\";}\n\ -.fa-file-excel-o:before {content: \"\\f1c3\";}\n\ -.fa-file-powerpoint-o:before {content: \"\\f1c4\";}\n\ -.fa-file-photo-o:before, .fa-file-picture-o:before, .fa-file-image-o:before {content: \"\\f1c5\";}\n\ -.fa-file-zip-o:before, .fa-file-archive-o:before {content: \"\\f1c6\";}\n\ -.fa-file-sound-o:before, .fa-file-audio-o:before {content: \"\\f1c7\";}\n\ -.fa-file-movie-o:before, .fa-file-video-o:before {content: \"\\f1c8\";}\n\ -.fa-file-code-o:before {content: \"\\f1c9\";}\n\ -.fa-vine:before {content: \"\\f1ca\";}\n\ -.fa-codepen:before {content: \"\\f1cb\";}\n\ -.fa-jsfiddle:before {content: \"\\f1cc\";}\n\ -.fa-life-bouy:before, .fa-life-buoy:before, .fa-life-saver:before, .fa-support:before, .fa-life-ring:before {content: \"\\f1cd\";}\n\ -.fa-circle-o-notch:before {content: \"\\f1ce\";}\n\ -.fa-ra:before, .fa-resistance:before, .fa-rebel:before {content: \"\\f1d0\";}\n\ -.fa-ge:before, .fa-empire:before {content: \"\\f1d1\";}\n\ -.fa-git-square:before {content: \"\\f1d2\";}\n\ -.fa-git:before {content: \"\\f1d3\";}\n\ -.fa-y-combinator-square:before, .fa-yc-square:before, .fa-hacker-news:before {content: \"\\f1d4\";}\n\ -.fa-tencent-weibo:before {content: \"\\f1d5\";}\n\ -.fa-qq:before {content: \"\\f1d6\";}\n\ -.fa-wechat:before, .fa-weixin:before {content: \"\\f1d7\";}\n\ -.fa-send:before, .fa-paper-plane:before {content: \"\\f1d8\";}\n\ -.fa-send-o:before, .fa-paper-plane-o:before {content: \"\\f1d9\";}\n\ -.fa-history:before {content: \"\\f1da\";}\n\ -.fa-circle-thin:before {content: \"\\f1db\";}\n\ -.fa-header:before {content: \"\\f1dc\";}\n\ -.fa-paragraph:before {content: \"\\f1dd\";}\n\ -.fa-sliders:before {content: \"\\f1de\";}\n\ -.fa-share-alt:before {content: \"\\f1e0\";}\n\ -.fa-share-alt-square:before {content: \"\\f1e1\";}\n\ -.fa-bomb:before {content: \"\\f1e2\";}\n\ -.fa-soccer-ball-o:before, .fa-futbol-o:before {content: \"\\f1e3\";}\n\ -.fa-tty:before {content: \"\\f1e4\";}\n\ -.fa-binoculars:before {content: \"\\f1e5\";}\n\ -.fa-plug:before {content: \"\\f1e6\";}\n\ -.fa-slideshare:before {content: \"\\f1e7\";}\n\ -.fa-twitch:before {content: \"\\f1e8\";}\n\ -.fa-yelp:before {content: \"\\f1e9\";}\n\ -.fa-newspaper-o:before {content: \"\\f1ea\";}\n\ -.fa-wifi:before {content: \"\\f1eb\";}\n\ -.fa-calculator:before {content: \"\\f1ec\";}\n\ -.fa-paypal:before {content: \"\\f1ed\";}\n\ -.fa-google-wallet:before {content: \"\\f1ee\";}\n\ -.fa-cc-visa:before {content: \"\\f1f0\";}\n\ -.fa-cc-mastercard:before {content: \"\\f1f1\";}\n\ -.fa-cc-discover:before {content: \"\\f1f2\";}\n\ -.fa-cc-amex:before {content: \"\\f1f3\";}\n\ -.fa-cc-paypal:before {content: \"\\f1f4\";}\n\ -.fa-cc-stripe:before {content: \"\\f1f5\";}\n\ -.fa-bell-slash:before {content: \"\\f1f6\";}\n\ -.fa-bell-slash-o:before {content: \"\\f1f7\";}\n\ -.fa-trash:before {content: \"\\f1f8\";}\n\ -.fa-copyright:before {content: \"\\f1f9\";}\n\ -.fa-at:before {content: \"\\f1fa\";}\n\ -.fa-eyedropper:before {content: \"\\f1fb\";}\n\ -.fa-paint-brush:before {content: \"\\f1fc\";}\n\ -.fa-birthday-cake:before {content: \"\\f1fd\";}\n\ -.fa-area-chart:before {content: \"\\f1fe\";}\n\ -.fa-pie-chart:before {content: \"\\f200\";}\n\ -.fa-line-chart:before {content: \"\\f201\";}\n\ -.fa-lastfm:before {content: \"\\f202\";}\n\ -.fa-lastfm-square:before {content: \"\\f203\";}\n\ -.fa-toggle-off:before {content: \"\\f204\";}\n\ -.fa-toggle-on:before {content: \"\\f205\";}\n\ -.fa-bicycle:before {content: \"\\f206\";}\n\ -.fa-bus:before {content: \"\\f207\";}\n\ -.fa-ioxhost:before {content: \"\\f208\";}\n\ -.fa-angellist:before {content: \"\\f209\";}\n\ -.fa-cc:before {content: \"\\f20a\";}\n\ -.fa-shekel:before, .fa-sheqel:before, .fa-ils:before {content: \"\\f20b\";}\n\ -.fa-meanpath:before {content: \"\\f20c\";}\n\ -.fa-buysellads:before {content: \"\\f20d\";}\n\ -.fa-connectdevelop:before {content: \"\\f20e\";}\n\ -.fa-dashcube:before {content: \"\\f210\";}\n\ -.fa-forumbee:before {content: \"\\f211\";}\n\ -.fa-leanpub:before {content: \"\\f212\";}\n\ -.fa-sellsy:before {content: \"\\f213\";}\n\ -.fa-shirtsinbulk:before {content: \"\\f214\";}\n\ -.fa-simplybuilt:before {content: \"\\f215\";}\n\ -.fa-skyatlas:before {content: \"\\f216\";}\n\ -.fa-cart-plus:before {content: \"\\f217\";}\n\ -.fa-cart-arrow-down:before {content: \"\\f218\";}\n\ -.fa-diamond:before {content: \"\\f219\";}\n\ -.fa-ship:before {content: \"\\f21a\";}\n\ -.fa-user-secret:before {content: \"\\f21b\";}\n\ -.fa-motorcycle:before {content: \"\\f21c\";}\n\ -.fa-street-view:before {content: \"\\f21d\";}\n\ -.fa-heartbeat:before {content: \"\\f21e\";}\n\ -.fa-venus:before {content: \"\\f221\";}\n\ -.fa-mars:before {content: \"\\f222\";}\n\ -.fa-mercury:before {content: \"\\f223\";}\n\ -.fa-intersex:before, .fa-transgender:before {content: \"\\f224\";}\n\ -.fa-transgender-alt:before {content: \"\\f225\";}\n\ -.fa-venus-double:before {content: \"\\f226\";}\n\ -.fa-mars-double:before {content: \"\\f227\";}\n\ -.fa-venus-mars:before {content: \"\\f228\";}\n\ -.fa-mars-stroke:before {content: \"\\f229\";}\n\ -.fa-mars-stroke-v:before {content: \"\\f22a\";}\n\ -.fa-mars-stroke-h:before {content: \"\\f22b\";}\n\ -.fa-neuter:before {content: \"\\f22c\";}\n\ -.fa-genderless:before {content: \"\\f22d\";}\n\ -.fa-facebook-official:before {content: \"\\f230\";}\n\ -.fa-pinterest-p:before {content: \"\\f231\";}\n\ -.fa-whatsapp:before {content: \"\\f232\";}\n\ -.fa-server:before {content: \"\\f233\";}\n\ -.fa-user-plus:before {content: \"\\f234\";}\n\ -.fa-user-times:before {content: \"\\f235\";}\n\ -.fa-hotel:before, .fa-bed:before {content: \"\\f236\";}\n\ -.fa-viacoin:before {content: \"\\f237\";}\n\ -.fa-train:before {content: \"\\f238\";}\n\ -.fa-subway:before {content: \"\\f239\";}\n\ -.fa-medium:before {content: \"\\f23a\";}\n\ -.fa-yc:before, .fa-y-combinator:before {content: \"\\f23b\";}\n\ -.fa-optin-monster:before {content: \"\\f23c\";}\n\ -.fa-opencart:before {content: \"\\f23d\";}\n\ -.fa-expeditedssl:before {content: \"\\f23e\";}\n\ -.fa-battery-4:before, .fa-battery:before, .fa-battery-full:before {content: \"\\f240\";}\n\ -.fa-battery-3:before, .fa-battery-three-quarters:before {content: \"\\f241\";}\n\ -.fa-battery-2:before, .fa-battery-half:before {content: \"\\f242\";}\n\ -.fa-battery-1:before, .fa-battery-quarter:before {content: \"\\f243\";}\n\ -.fa-battery-0:before, .fa-battery-empty:before {content: \"\\f244\";}\n\ -.fa-mouse-pointer:before {content: \"\\f245\";}\n\ -.fa-i-cursor:before {content: \"\\f246\";}\n\ -.fa-object-group:before {content: \"\\f247\";}\n\ -.fa-object-ungroup:before {content: \"\\f248\";}\n\ -.fa-sticky-note:before {content: \"\\f249\";}\n\ -.fa-sticky-note-o:before {content: \"\\f24a\";}\n\ -.fa-cc-jcb:before {content: \"\\f24b\";}\n\ -.fa-cc-diners-club:before {content: \"\\f24c\";}\n\ -.fa-clone:before {content: \"\\f24d\";}\n\ -.fa-balance-scale:before {content: \"\\f24e\";}\n\ -.fa-hourglass-o:before {content: \"\\f250\";}\n\ -.fa-hourglass-1:before, .fa-hourglass-start:before {content: \"\\f251\";}\n\ -.fa-hourglass-2:before, .fa-hourglass-half:before {content: \"\\f252\";}\n\ -.fa-hourglass-3:before, .fa-hourglass-end:before {content: \"\\f253\";}\n\ -.fa-hourglass:before {content: \"\\f254\";}\n\ -.fa-hand-grab-o:before, .fa-hand-rock-o:before {content: \"\\f255\";}\n\ -.fa-hand-stop-o:before, .fa-hand-paper-o:before {content: \"\\f256\";}\n\ -.fa-hand-scissors-o:before {content: \"\\f257\";}\n\ -.fa-hand-lizard-o:before {content: \"\\f258\";}\n\ -.fa-hand-spock-o:before {content: \"\\f259\";}\n\ -.fa-hand-pointer-o:before {content: \"\\f25a\";}\n\ -.fa-hand-peace-o:before {content: \"\\f25b\";}\n\ -.fa-trademark:before {content: \"\\f25c\";}\n\ -.fa-registered:before {content: \"\\f25d\";}\n\ -.fa-creative-commons:before {content: \"\\f25e\";}\n\ -.fa-gg:before {content: \"\\f260\";}\n\ -.fa-gg-circle:before {content: \"\\f261\";}\n\ -.fa-tripadvisor:before {content: \"\\f262\";}\n\ -.fa-odnoklassniki:before {content: \"\\f263\";}\n\ -.fa-odnoklassniki-square:before {content: \"\\f264\";}\n\ -.fa-get-pocket:before {content: \"\\f265\";}\n\ -.fa-wikipedia-w:before {content: \"\\f266\";}\n\ -.fa-safari:before {content: \"\\f267\";}\n\ -.fa-chrome:before {content: \"\\f268\";}\n\ -.fa-firefox:before {content: \"\\f269\";}\n\ -.fa-opera:before {content: \"\\f26a\";}\n\ -.fa-internet-explorer:before {content: \"\\f26b\";}\n\ -.fa-tv:before, .fa-television:before {content: \"\\f26c\";}\n\ -.fa-contao:before {content: \"\\f26d\";}\n\ -.fa-500px:before {content: \"\\f26e\";}\n\ -.fa-amazon:before {content: \"\\f270\";}\n\ -.fa-calendar-plus-o:before {content: \"\\f271\";}\n\ -.fa-calendar-minus-o:before {content: \"\\f272\";}\n\ -.fa-calendar-times-o:before {content: \"\\f273\";}\n\ -.fa-calendar-check-o:before {content: \"\\f274\";}\n\ -.fa-industry:before {content: \"\\f275\";}\n\ -.fa-map-pin:before {content: \"\\f276\";}\n\ -.fa-map-signs:before {content: \"\\f277\";}\n\ -.fa-map-o:before {content: \"\\f278\";}\n\ -.fa-map:before {content: \"\\f279\";}\n\ -.fa-commenting:before {content: \"\\f27a\";}\n\ -.fa-commenting-o:before {content: \"\\f27b\";}\n\ -.fa-houzz:before {content: \"\\f27c\";}\n\ -.fa-vimeo:before {content: \"\\f27d\";}\n\ -.fa-black-tie:before {content: \"\\f27e\";}\n\ -.fa-fonticons:before {content: \"\\f280\";}\n\ -.fa-reddit-alien:before {content: \"\\f281\";}\n\ -.fa-edge:before {content: \"\\f282\";}\n\ -.fa-credit-card-alt:before {content: \"\\f283\";}\n\ -.fa-codiepie:before {content: \"\\f284\";}\n\ -.fa-modx:before {content: \"\\f285\";}\n\ -.fa-fort-awesome:before {content: \"\\f286\";}\n\ -.fa-usb:before {content: \"\\f287\";}\n\ -.fa-product-hunt:before {content: \"\\f288\";}\n\ -.fa-mixcloud:before {content: \"\\f289\";}\n\ -.fa-scribd:before {content: \"\\f28a\";}\n\ -.fa-pause-circle:before {content: \"\\f28b\";}\n\ -.fa-pause-circle-o:before {content: \"\\f28c\";}\n\ -.fa-stop-circle:before {content: \"\\f28d\";}\n\ -.fa-stop-circle-o:before {content: \"\\f28e\";}\n\ -.fa-shopping-bag:before {content: \"\\f290\";}\n\ -.fa-shopping-basket:before {content: \"\\f291\";}\n\ -.fa-hashtag:before {content: \"\\f292\";}\n\ -.fa-bluetooth:before {content: \"\\f293\";}\n\ -.fa-bluetooth-b:before {content: \"\\f294\";}\n\ -.fa-percent:before {content: \"\\f295\";}\n\ -.fa-gitlab:before {content: \"\\f296\";}\n\ -.fa-wpbeginner:before {content: \"\\f297\";}\n\ -.fa-wpforms:before {content: \"\\f298\";}\n\ -.fa-envira:before {content: \"\\f299\";}\n\ -.fa-universal-access:before {content: \"\\f29a\";}\n\ -.fa-wheelchair-alt:before {content: \"\\f29b\";}\n\ -.fa-question-circle-o:before {content: \"\\f29c\";}\n\ -.fa-blind:before {content: \"\\f29d\";}\n\ -.fa-audio-description:before {content: \"\\f29e\";}\n\ -.fa-volume-control-phone:before {content: \"\\f2a0\";}\n\ -.fa-braille:before {content: \"\\f2a1\";}\n\ -.fa-assistive-listening-systems:before {content: \"\\f2a2\";}\n\ -.fa-asl-interpreting:before, .fa-american-sign-language-interpreting:before {content: \"\\f2a3\";}\n\ -.fa-deafness:before, .fa-hard-of-hearing:before, .fa-deaf:before {content: \"\\f2a4\";}\n\ -.fa-glide:before {content: \"\\f2a5\";}\n\ -.fa-glide-g:before {content: \"\\f2a6\";}\n\ -.fa-signing:before, .fa-sign-language:before {content: \"\\f2a7\";}\n\ -.fa-low-vision:before {content: \"\\f2a8\";}\n\ -.fa-viadeo:before {content: \"\\f2a9\";}\n\ -.fa-viadeo-square:before {content: \"\\f2aa\";}\n\ -.fa-snapchat:before {content: \"\\f2ab\";}\n\ -.fa-snapchat-ghost:before {content: \"\\f2ac\";}\n\ -.fa-snapchat-square:before {content: \"\\f2ad\";}\n\ -.fa-pied-piper:before {content: \"\\f2ae\";}\n\ -.fa-first-order:before {content: \"\\f2b0\";}\n\ -.fa-yoast:before {content: \"\\f2b1\";}\n\ -.fa-themeisle:before {content: \"\\f2b2\";}\n\ -.fa-google-plus-circle:before, .fa-google-plus-official:before {content: \"\\f2b3\";}\n\ -.fa-fa:before, .fa-font-awesome:before {content: \"\\f2b4\";}\n\ -.fa-handshake-o:before {content: \"\\f2b5\";}\n\ -.fa-envelope-open:before {content: \"\\f2b6\";}\n\ -.fa-envelope-open-o:before {content: \"\\f2b7\";}\n\ -.fa-linode:before {content: \"\\f2b8\";}\n\ -.fa-address-book:before {content: \"\\f2b9\";}\n\ -.fa-address-book-o:before {content: \"\\f2ba\";}\n\ -.fa-vcard:before, .fa-address-card:before {content: \"\\f2bb\";}\n\ -.fa-vcard-o:before, .fa-address-card-o:before {content: \"\\f2bc\";}\n\ -.fa-user-circle:before {content: \"\\f2bd\";}\n\ -.fa-user-circle-o:before {content: \"\\f2be\";}\n\ -.fa-user-o:before {content: \"\\f2c0\";}\n\ -.fa-id-badge:before {content: \"\\f2c1\";}\n\ -.fa-drivers-license:before, .fa-id-card:before {content: \"\\f2c2\";}\n\ -.fa-drivers-license-o:before, .fa-id-card-o:before {content: \"\\f2c3\";}\n\ -.fa-quora:before {content: \"\\f2c4\";}\n\ -.fa-free-code-camp:before {content: \"\\f2c5\";}\n\ -.fa-telegram:before {content: \"\\f2c6\";}\n\ -.fa-thermometer-4:before, .fa-thermometer:before, .fa-thermometer-full:before {content: \"\\f2c7\";}\n\ -.fa-thermometer-3:before, .fa-thermometer-three-quarters:before {content: \"\\f2c8\";}\n\ -.fa-thermometer-2:before, .fa-thermometer-half:before {content: \"\\f2c9\";}\n\ -.fa-thermometer-1:before, .fa-thermometer-quarter:before {content: \"\\f2ca\";}\n\ -.fa-thermometer-0:before, .fa-thermometer-empty:before {content: \"\\f2cb\";}\n\ -.fa-shower:before {content: \"\\f2cc\";}\n\ -.fa-bathtub:before, .fa-s15:before, .fa-bath:before {content: \"\\f2cd\";}\n\ -.fa-podcast:before {content: \"\\f2ce\";}\n\ -.fa-window-maximize:before {content: \"\\f2d0\";}\n\ -.fa-window-minimize:before {content: \"\\f2d1\";}\n\ -.fa-window-restore:before {content: \"\\f2d2\";}\n\ -.fa-times-rectangle:before, .fa-window-close:before {content: \"\\f2d3\";}\n\ -.fa-times-rectangle-o:before, .fa-window-close-o:before {content: \"\\f2d4\";}\n\ -.fa-bandcamp:before {content: \"\\f2d5\";}\n\ -.fa-grav:before {content: \"\\f2d6\";}\n\ -.fa-etsy:before {content: \"\\f2d7\";}\n\ -.fa-imdb:before {content: \"\\f2d8\";}\n\ -.fa-ravelry:before {content: \"\\f2d9\";}\n\ -.fa-eercast:before {content: \"\\f2da\";}\n\ -.fa-microchip:before {content: \"\\f2db\";}\n\ -.fa-snowflake-o:before {content: \"\\f2dc\";}\n\ -.fa-superpowers:before {content: \"\\f2dd\";}\n\ -.fa-wpexplorer:before {content: \"\\f2de\";}\n\ -.fa-meetup:before {content: \"\\f2e0\";}\n\ -.fa::before {\n\ - font-family: FontAwesome;\n\ - font-weight: 400;\n\ - font-style: normal;\n\ - -webkit-font-smoothing: antialiased;\n\ - text-decoration: inherit;\n\ - speak: none;\n\ - display: inline-block;\n\ - font-size: 13px;\n\ - visibility: visible;\n\ -}\n\ -:root:not(.shortcut-icons) #shortcuts .fa::before {\n\ - display: none;\n\ -}\n\ -:root.shortcut-icons #shortcuts .fa::before {\n\ - font-size: 15px !important;\n\ - margin-top: -3px !important;\n\ - position: relative;\n\ - top: 1px;\n\ -}\n\ -:root.shortcut-icons #shortcuts .fa, .menu-button .fa {\n\ - font-size: 0;\n\ - visibility: hidden;\n\ -}\n\ -:root.shortcut-icons .shortcut.brackets-wrap::after,\n\ -:root.shortcut-icons .shortcut.brackets-wrap::before {\n\ - display: none;\n\ -}\n\ -:root.shortcut-icons #shortcuts a .fa,\n\ -.menu-button .fa,\n\ -.hide-reply-button .fa,\n\ -.hide-thread-button .fa {\n\ - display: inline;\n\ -}\n\ -.fa-spin::before {\n\ - -webkit-animation:spin 2s infinite linear;\n\ - -moz-animation:spin 2s infinite linear;\n\ - -o-animation:spin 2s infinite linear;\n\ - animation:spin 2s infinite linear;\n\ -}\n\ -@-moz-keyframes spin {\n\ - 0% {-moz-transform:rotate(0deg);}\n\ - 100% {-moz-transform:rotate(359deg);}\n\ -}\n\ -@-webkit-keyframes spin {\n\ - 0% {-webkit-transform:rotate(0deg);}\n\ - 100% {-webkit-transform:rotate(359deg);}\n\ -}\n\ -@keyframes spin {\n\ - 0% {transform:rotate(0deg);}\n\ - 100% {transform:rotate(359deg);}\n\ -}\n\ -/* General */\n\ -.dialog {\n\ - border: 1px solid;\n\ - display: block;\n\ - background-color: inherit;\n\ -}\n\ -.dialog:not(#qr):not(#thread-watcher):not(#header-bar) {\n\ - box-shadow: 0 1px 2px rgba(0, 0, 0, .15);\n\ -}\n\ -#qr,\n\ -#thread-watcher {\n\ - box-shadow: -1px 2px 2px rgba(0, 0, 0, 0.25);\n\ -}\n\ -.captcha-img,\n\ -.field {\n\ - background-color: #FFF;\n\ - border: 1px solid #CCC;\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - color: #333;\n\ - font: 13px sans-serif;\n\ - outline: none;\n\ - transition: color .25s, border-color .25s;\n\ -}\n\ -.field::-moz-placeholder {\n\ - color: #AAA;\n\ - font-size: 13px;\n\ - opacity: 1;\n\ -}\n\ -.captch-img:hover,\n\ -.field:hover {\n\ - border-color: #999;\n\ -}\n\ -.field:hover, .field:focus, .field.focus {\n\ - color: #000;\n\ -}\n\ -.field[disabled] {\n\ - background-color: #F2F2F2;\n\ - color: #888;\n\ -}\n\ -.field::-webkit-search-decoration {\n\ - display: none;\n\ -}\n\ -.move {\n\ - cursor: move;\n\ - overflow: hidden;\n\ -}\n\ -label {\n\ - cursor: pointer;\n\ -}\n\ -a[href=\"javascript:;\"] {\n\ - text-decoration: none;\n\ -}\n\ -.warning {\n\ - color: red;\n\ -}\n\ -:root.sw-yotsuba #boardNavDesktop, :root.sw-yotsuba #boardNavMobile {\n\ - display: none !important;\n\ -}\n\ -:root.hide-bottom-board-list $site$boardListBottom {\n\ - display: none;\n\ -}\n\ -body.hasDropDownNav{\n\ - margin-top: 5px;\n\ -}\n\ -:root:not(.keyboard-focus) a {\n\ - outline: none;\n\ -}\n\ -.painted {\n\ - border-radius: 3px;\n\ - padding: 0px 2px;\n\ -}\n\ -[hidden] {\n\ - display: none !important;\n\ -}\n\ -/* 4chan style fixes */\n\ -/* overrides 4chan CSS on div.opContainer, div.op */\n\ -:root.sw-yotsuba .opContainer, :root.sw-yotsuba .op {\n\ - display: block;\n\ - overflow: visible;\n\ -}\n\ -:root.sw-yotsuba .reply > .file > .fileText {\n\ - margin: 0 20px;\n\ -}\n\ -:root.sw-yotsuba #arc-list span.quote {\n\ - color: #789922;\n\ -}\n\ -:root.sw-yotsuba .fileText a {\n\ - unicode-bidi: -moz-isolate;\n\ - unicode-bidi: -webkit-isolate;\n\ -}\n\ -:root.sw-yotsuba #g-recaptcha {\n\ - min-height: 78px;\n\ - height: auto;\n\ -}\n\ -:root.sw-yotsuba:not(.js-enabled) #postForm {\n\ - display: table;\n\ -}\n\ -:root.sw-yotsuba #captchaContainerAlt td:nth-child(2) {\n\ - display: table-cell !important;\n\ -}\n\ -:root.sw-yotsuba canvas#tegaki-canvas {\n\ - background: none;\n\ -}\n\ -/* Disable obnoxious captcha fade-in. */\n\ -:root.sw-yotsuba > body > div:last-of-type {\n\ - transition: none !important;\n\ -}\n\ -/* Fix captcha scrolling to top of page. */\n\ -:root.sw-yotsuba > body > div[style*=\" top: -10000px;\"] {\n\ - visibility: hidden !important;\n\ -}\n\ -/* Make long filenames wrap properly: https://github.com/ccd0/4chan-x/issues/1082 */\n\ -:root.sw-yotsuba .post > .file {\n\ - /* currently nonstandard but may be added: https://lists.w3.org/Archives/Public/www-style/2016Mar/0352.html, https://bugzilla.mozilla.org/show_bug.cgi?id=1296042 */\n\ - word-break: break-word;\n\ -}\n\ -:root.sw-yotsuba:not(.ua-webkit):not(.ua-blink) .fileText {\n\ - word-wrap: break-word;\n\ - max-width: calc(100vw - 90px);\n\ -}\n\ -:root.sw-yotsuba > body.is_catalog .thread > a > img {\n\ - display: inline-block;\n\ -}\n\ -/* Links to NSFW boards */\n\ -:root.sw-yotsuba .nwsb {\n\ - display: inline;\n\ -}\n\ -:root.sw-yotsuba .fileText {\n\ - max-width: auto;\n\ - white-space: normal;\n\ -}\n\ -/* Ads */\n\ -:root.sw-yotsuba .ad-cnt > *, :root.sw-yotsuba .adg-rects > *, :root.sw-yotsuba .bsa-cnt {\n\ - height: auto !important;\n\ -}\n\ -:root.sw-yotsuba:not(.ads-loaded) hr.abovePostForm,\n\ -:root.sw-yotsuba:not(.ads-loaded) .adg-rects > hr,\n\ -:root.sw-yotsuba #adg-ol + hr,\n\ -:root.sw-yotsuba .danbo-slot:empty {\n\ - display: none;\n\ -}\n\ -:root.sw-yotsuba .adg-rects {\n\ - margin: 0;\n\ - font-size: 0;\n\ -}\n\ -:root.sw-yotsuba div.center[style] {\n\ - display: none !important;\n\ -}\n\ -/* Tinyboard / vichan conflicts */\n\ -#menu > .hide-thread-link {\n\ - width: auto;\n\ - height: auto;\n\ - overflow: visible;\n\ - background-image: none;\n\ -}\n\ -#menu label.entry {\n\ - display: block;\n\ -}\n\ -#fourchanx-settings label {\n\ - display: inline;\n\ -}\n\ -.intro a[href=\"javascript:;\"],\n\ -#menu a {\n\ - margin: 0;\n\ -}\n\ -.gal-buttons.gal-buttons a {\n\ - font-size: inherit;\n\ -}\n\ -:root.sw-tinyboard.fixed.top-header:not(.autohide) .boardlist,\n\ -:root.sw-tinyboard.fixed.top-header:not(.autohide) .bar.top {\n\ - position: static;\n\ -}\n\ -:root.sw-tinyboard.fixed.top-header:not(.autohide) div.pages.top {\n\ - top: auto;\n\ - bottom: 0;\n\ -}\n\ -:root.sw-tinyboard.fixed.top-header.autohide .boardlist,\n\ -:root.sw-tinyboard.fixed.top-header.autohide .bar.top {\n\ - z-index: 3;\n\ -}\n\ -/* Tinyboard site style conflicts */\n\ -:root[data-host=\"fufufu.moe\"].fixed.top-header:not(.autohide) div.pages.top {\n\ - top: 26px;\n\ - bottom: auto;\n\ -}\n\ -:root[data-host=\"merorin.com\"].fixed.top-header:not(.autohide) span.settings {\n\ - top: 26px;\n\ -}\n\ -:root[data-host=\"fufufu.moe\"]:not(.fixed) #header-bar {\n\ - margin-top: 38px;\n\ -}\n\ -:root[data-host=\"lainchan.org\"]:not(.fixed) #header-bar {\n\ - margin-top: 17px;\n\ -}\n\ -:root[data-host=\"smuglo.li\"]:not(.fixed) #header-bar {\n\ - margin-top: 8px;\n\ -}\n\ -/* Anti-autoplay */\n\ -audio.controls-added {\n\ - display: block;\n\ - margin: auto;\n\ - white-space: normal;\n\ -}\n\ -:root.anti-autoplay div.embed {\n\ - position: static;\n\ - width: auto;\n\ - height: auto;\n\ - text-align: center;\n\ -}\n\ -:root.anti-autoplay .autoplay-removed {\n\ - visibility: visible !important;\n\ - min-width: 640px;\n\ - min-height: 360px;\n\ -}\n\ -/* fixed, z-index */\n\ -#overlay,\n\ -#qp, #ihover,\n\ -#navlinks, .fixed #header-bar,\n\ -:root.float #updater,\n\ -:root.float #thread-stats,\n\ -#qr {\n\ - position: fixed;\n\ -}\n\ -#overlay {\n\ - z-index: 999;\n\ -}\n\ -#qp, #ihover {\n\ - z-index: 60;\n\ -}\n\ -#menu, .gal-buttons {\n\ - z-index: 50;\n\ -}\n\ -#updater, #thread-stats {\n\ - z-index: 40;\n\ -}\n\ -:root.fixed #header-bar, #notifications {\n\ - z-index: 35;\n\ -}\n\ -#a-gallery {\n\ - z-index: 30;\n\ -}\n\ -#navlinks {\n\ - z-index: 25;\n\ -}\n\ -#qr {\n\ - z-index: 20;\n\ -}\n\ -#embedding {\n\ - z-index: 11;\n\ -}\n\ -:root.fixed-watcher #thread-watcher {\n\ - z-index: 10;\n\ -}\n\ -:root.fixed:not(.gallery-open) #header-bar:not(:hover) {\n\ - z-index: 8;\n\ -}\n\ -#thread-watcher {\n\ - z-index: 5;\n\ -}\n\ -/* Header */\n\ -.fixed.top-header body {\n\ - padding-top: 2em;\n\ -}\n\ -.fixed.bottom-header body {\n\ - padding-bottom: 2em;\n\ -}\n\ -.fixed #header-bar {\n\ - right: 0;\n\ - left: 0;\n\ - padding: 3px 4px 4px;\n\ - font-size: 12px;\n\ -}\n\ -.fixed.top-header #header-bar {\n\ - top: 0;\n\ -}\n\ -.fixed.bottom-header #header-bar {\n\ - bottom: 0;\n\ -}\n\ -#header-bar {\n\ - border-width: 0;\n\ - transition: all .1s .05s ease-in-out;\n\ -}\n\ -:root.fixed #header-bar {\n\ - box-shadow: -5px 1px 10px rgba(0, 0, 0, 0.20);\n\ -}\n\ -:root.centered-links #shortcuts {\n\ - width: 300px;\n\ - text-align: right;\n\ -}\n\ -:root.centered-links #header-bar {\n\ - text-align: center;\n\ -}\n\ -#custom-board-list {\n\ - font-size: 13px;\n\ - vertical-align: middle;\n\ -}\n\ -#full-board-list {\n\ - vertical-align: middle;\n\ -}\n\ -:root.centered-links #custom-board-list {\n\ - position: relative;\n\ - left: 150px;\n\ -}\n\ -.fixed.top-header #header-bar {\n\ - border-bottom-width: 1px;\n\ -}\n\ -.fixed.bottom-header #header-bar {\n\ - box-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\n\ - border-top-width: 1px;\n\ -}\n\ -.fixed.bottom-header #header-bar .menu-button i {\n\ - border-top: none;\n\ - border-bottom: 6px solid;\n\ -}\n\ -.fixed #header-bar.autohide:not(:hover) {\n\ - box-shadow: none;\n\ - transition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n\ -}\n\ -.fixed.top-header #header-bar.autohide:not(:hover) {\n\ - margin-bottom: -1em;\n\ - -webkit-transform: translateY(-100%);\n\ - transform: translateY(-100%);\n\ -}\n\ -.fixed.bottom-header #header-bar.autohide:not(:hover) {\n\ - -webkit-transform: translateY(100%);\n\ - transform: translateY(100%);\n\ -}\n\ -#scroll-marker {\n\ - left: 0;\n\ - right: 0;\n\ - height: 10px;\n\ - position: absolute;\n\ -}\n\ -#header-bar:not(.autohide) #scroll-marker {\n\ - pointer-events: none;\n\ -}\n\ -#header-bar #scroll-marker {\n\ - display: none;\n\ -}\n\ -.fixed #header-bar #scroll-marker {\n\ - display: block;\n\ -}\n\ -.fixed.top-header #header-bar #scroll-marker {\n\ - top: 100%;\n\ -}\n\ -.fixed.bottom-header #header-bar #scroll-marker {\n\ - bottom: 100%;\n\ -}\n\ -#board-list a, #shortcuts a:not(.entry) {\n\ - text-decoration: none;\n\ - padding: 1px;\n\ -}\n\ -#shortcuts:empty {\n\ - display: none;\n\ -}\n\ -.brackets-wrap::before {\n\ - content: \"\\00a0[\";\n\ -}\n\ -.brackets-wrap::after {\n\ - content: \"]\\00a0\";\n\ -}\n\ -.dead-thread,\n\ -.disabled:not(.replies-quoting-you) {\n\ - opacity: .45;\n\ -}\n\ -#shortcuts {\n\ - float: right;\n\ -}\n\ -:root.autohiding-scrollbar #shortcuts {\n\ - margin-right: 12px;\n\ -}\n\ -.shortcut {\n\ - margin-left: 3px;\n\ - vertical-align: middle;\n\ -}\n\ -:root.shortcut-icons .native-settings {\n\ - font-size: 0;\n\ - color: transparent;\n\ - display: inline-block;\n\ - vertical-align: top;\n\ - height: 12px;\n\ - width: 14px;\n\ - background: url('//s.4cdn.org/image/favicon.ico') 0px -1px no-repeat;\n\ -}\n\ -#navbotright,\n\ -#navtopright {\n\ - display: none;\n\ -}\n\ -#toggleMsgBtn {\n\ - display: none !important;\n\ -}\n\ -.current,\n\ -:root.sw-yotsuba div#boardNavDesktopFoot a.current {\n\ - font-weight: bold;\n\ -}\n\ -@media (min-width: 1300px) {\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #header-bar {\n\ - white-space: nowrap;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #board-list {\n\ - -webkit-flex: auto;\n\ - flex: auto;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) .hide-board-list-container {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - margin-right: 5px;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList {\n\ - -webkit-flex: auto;\n\ - flex: auto;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - width: 0px; /* XXX Fixes Edge not shrinking the board list below default size when needed */\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > a,\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span:not(.space):not(.spacer) {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - padding: .17em;\n\ - margin: -.17em -.32em;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span {\n\ - pointer-events: none;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span.space {\n\ - -webkit-flex: 0 .63 .63em;\n\ - flex: 0 .63 .63em;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #full-board-list > .boardList > span.spacer {\n\ - -webkit-flex: 0 .38 .38em;\n\ - flex: 0 .38 .38em;\n\ - }\n\ - :root.sw-yotsuba.fixed:not(.centered-links) #shortcuts {\n\ - float: initial;\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - }\n\ -}\n\ -/* 4chan X link brackets */\n\ -.brackets-wrap::before {\n\ - content: \"[\";\n\ -}\n\ -.brackets-wrap::after {\n\ - content: \"]\";\n\ -}\n\ -/* Notifications */\n\ -#notifications {\n\ - position: fixed;\n\ - top: 0;\n\ - height: 0;\n\ - text-align: center;\n\ - right: 0;\n\ - left: 0;\n\ - visibility: visible;\n\ -}\n\ -#notifications:empty {\n\ - display: none;\n\ -}\n\ -:root.fixed.top-header:not(.gallery-open) #header-bar #notifications,\n\ -:root.fixed.top-header #header-bar.autohide #notifications {\n\ - position: absolute;\n\ - top: 100%;\n\ -}\n\ -.notification {\n\ - color: #FFF;\n\ - font-weight: 700;\n\ - text-shadow: 0 1px 2px rgba(0, 0, 0, .5);\n\ - box-shadow: 0 1px 2px rgba(0, 0, 0, .15);\n\ - border-radius: 2px;\n\ - margin: 1px auto;\n\ - width: 550px;\n\ - max-width: 100%;\n\ - position: relative;\n\ - transition: all .25s ease-in-out;\n\ -}\n\ -.notification.error {\n\ - background-color: hsla(0, 100%, 38%, .9);\n\ -}\n\ -.notification.warning {\n\ - background-color: hsla(36, 100%, 38%, .9);\n\ -}\n\ -.notification.info {\n\ - background-color: hsla(200, 100%, 38%, .9);\n\ -}\n\ -.notification.success {\n\ - background-color: hsla(104, 100%, 38%, .9);\n\ -}\n\ -.notification a {\n\ - color: white;\n\ -}\n\ -.notification > .close {\n\ - padding: 7px;\n\ - top: 0px;\n\ - right: 5px;\n\ - position: absolute;\n\ -}\n\ -.notification > .fa-times::before {\n\ - font-size: 11px !important;\n\ -}\n\ -.message {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - padding: 6px 20px;\n\ - max-height: 200px;\n\ - width: 100%;\n\ - overflow: auto;\n\ - white-space: pre-line;\n\ -}\n\ -.message a {\n\ - text-decoration: underline;\n\ -}\n\ -:root.tainted .report-error {\n\ - display: none;\n\ -}\n\ -/* Settings */\n\ -:root.fourchan-x body {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ -}\n\ -#overlay {\n\ - background-color: rgba(0, 0, 0, .5);\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - top: 0;\n\ - left: 0;\n\ - height: 100%;\n\ - width: 100%;\n\ -}\n\ -#fourchanx-settings {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - box-shadow: 0 0 15px rgba(0, 0, 0, .15);\n\ - height: 600px;\n\ - max-height: 100%;\n\ - width: 900px;\n\ - max-width: 100%;\n\ - margin: auto;\n\ - padding: 5px;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: column;\n\ - flex-direction: column;\n\ -}\n\ -#fourchanx-settings > nav {\n\ - padding: 2px 2px 8px;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ -}\n\ -#fourchanx-settings > nav a {\n\ - text-decoration: underline;\n\ -}\n\ -#fourchanx-settings > nav a.close {\n\ - text-decoration: none;\n\ - padding: 0 2px;\n\ - margin: 0;\n\ -}\n\ -.section-container {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ - position: relative;\n\ - overflow: auto;\n\ - padding-right: 5px;\n\ - overscroll-behavior: contain;\n\ -}\n\ -.sections-list {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ -}\n\ -.export, .import, .reset {\n\ - cursor: pointer;\n\ - text-decoration: none !important;\n\ -}\n\ -.tab-selected {\n\ - font-weight: 700;\n\ -}\n\ -.section-sauce ul,\n\ -.section-advanced ul {\n\ - list-style: none;\n\ - margin: 0;\n\ -}\n\ -.section-sauce ul {\n\ - padding: 8px;\n\ -}\n\ -.section-advanced ul {\n\ - padding: 0px;\n\ -}\n\ -.section-sauce li,\n\ -.section-advanced li {\n\ - padding-left: 4px;\n\ -}\n\ -.section-main ul {\n\ - margin: 0;\n\ - padding: 0 0 0 16px;\n\ -}\n\ -.section-main li {\n\ - white-space: pre-line;\n\ - list-style: disc;\n\ -}\n\ -.section-main li:not(:first-of-type) {\n\ - margin-top: 4px;\n\ -}\n\ -.section-main label {\n\ - text-decoration: underline;\n\ -}\n\ -div[data-checked=\"false\"] > .suboption-list {\n\ - display: none;\n\ -}\n\ -.suboption-list {\n\ - position: relative;\n\ -}\n\ -.suboption-list::before {\n\ - content: \"\";\n\ - display: inline-block;\n\ - position: absolute;\n\ - left: .7em;\n\ - width: 0;\n\ - height: 100%;\n\ - border-left: 1px solid;\n\ -}\n\ -.suboption-list > div {\n\ - position: relative;\n\ - padding-left: 1.4em;\n\ -}\n\ -.suboption-list > div::before {\n\ - content: \"\";\n\ - display: inline-block;\n\ - position: absolute;\n\ - left: .7em;\n\ - width: .7em;\n\ - height: .6em;\n\ - border-left: 1px solid;\n\ - border-bottom: 1px solid;\n\ -}\n\ -#fourchanx-settings .section-main p {\n\ - margin: .5em 0 0;\n\ -}\n\ -.section-filter ul {\n\ - padding: 0;\n\ -}\n\ -.section-filter li {\n\ - margin: 10px 40px;\n\ - list-style: disc;\n\ -}\n\ -.section-filter textarea {\n\ - height: 500px;\n\ -}\n\ -.section-main a, .section-filter a, .section-advanced a {\n\ - text-decoration: underline;\n\ -}\n\ -#sauce-doc-expand:not(:checked) ~ #sauce-doc {\n\ - max-height: 130px;\n\ - overflow: auto;\n\ -}\n\ -#sauce-doc > label {\n\ - float: right;\n\ - margin: 0 5px;\n\ -}\n\ -/* XXX for OneeChan */\n\ -#sauce-doc-expand + .riceCheck {\n\ - display: none;\n\ -}\n\ -.section-sauce textarea {\n\ - height: 430px;\n\ -}\n\ -.section-advanced .field[name=\"boardnav\"] {\n\ - width: 100%;\n\ -}\n\ -.section-advanced textarea {\n\ - height: 150px;\n\ -}\n\ -.section-advanced textarea[name=\"archiveLists\"],\n\ -.section-advanced textarea[name=\"externalCatalogURLs\"],\n\ -.section-advanced textarea[name=\"knownBanners\"] {\n\ - height: 75px;\n\ -}\n\ -.section-advanced .archive-cell {\n\ - min-width: 160px;\n\ - text-align: center;\n\ -}\n\ -.section-advanced #archive-board-select {\n\ - position: absolute;\n\ -}\n\ -.section-advanced .note {\n\ - font-size: 0.8em;\n\ - font-style: italic;\n\ - margin-left: 10px;\n\ -}\n\ -.section-advanced .note code {\n\ - font-style: normal;\n\ - font-size: 11px;\n\ -}\n\ -.favicon-preview > img {\n\ - vertical-align: middle;\n\ -}\n\ -.favicon-preview > img:nth-of-type(3n+1) {\n\ - margin-left: 4px;\n\ -}\n\ -.section-keybinds .field {\n\ - font-family: monospace;\n\ -}\n\ -#fourchanx-settings fieldset {\n\ - border: 1px solid;\n\ - border-radius: 3px;\n\ - padding: 0.35em 0.625em 0.75em;\n\ - margin: 0px 2px;\n\ -}\n\ -#fourchanx-settings legend {\n\ - font-weight: 700;\n\ - color: inherit;\n\ -}\n\ -#fourchanx-settings textarea {\n\ - font-family: monospace;\n\ - width: 100%;\n\ - resize: vertical;\n\ -}\n\ -#fourchanx-settings code {\n\ - color: #000;\n\ - background-color: #FFF;\n\ - padding: 0 2px;\n\ -}\n\ -#fourchanx-settings th {\n\ - text-align: center;\n\ - font-weight: bold;\n\ -}\n\ -#fourchanx-settings p {\n\ - margin: 1em 0px;\n\ -}\n\ -#fourchanx-settings table {\n\ - margin: auto;\n\ -}\n\ -/* Index */\n\ -:root.index-loading .navLinks:not(.json-index),\n\ -:root.index-loading .board:not(.json-index),\n\ -:root.index-loading .pagelist:not(.json-index),\n\ -:root.infinite-mode .pagelist,\n\ -:root.all-pages-mode .pagelist,\n\ -:root.catalog-mode .pagelist,\n\ -:root:not(.catalog-mode) .indexlink,\n\ -:root.catalog-mode .cataloglink,\n\ -:root:not(.catalog-mode) #hidden-label,\n\ -:root:not(.catalog-mode) #index-size {\n\ - display: none;\n\ -}\n\ -#index-search {\n\ - padding-right: 1.5em;\n\ - width: 100px;\n\ - transition: color .25s, border-color .25s, width .25s;\n\ -}\n\ -#index-search:focus,\n\ -#index-search[data-searching] {\n\ - width: 200px;\n\ -}\n\ -#index-search-clear {\n\ - color: gray;\n\ - display: inline-block;\n\ - position: relative;\n\ - left: -1em;\n\ - width: 0;\n\ -}\n\ -/* ``::-webkit-*'' selectors break selector lists on Firefox. */\n\ -#index-search::-webkit-search-cancel-button {\n\ - display: none;\n\ -}\n\ -#index-search:not([data-searching]) + #index-search-clear {\n\ - display: none;\n\ -}\n\ -#index-options {\n\ - float: right;\n\ -}\n\ -#lastlong-options {\n\ - display: inline-block;\n\ - vertical-align: middle;\n\ - height: 28px;\n\ - margin: -14px 0;\n\ -}\n\ -#lastlong-options > input {\n\ - padding: 0;\n\ - border: 0 !important;\n\ - text-align: center;\n\ - background: transparent;\n\ - display: block;\n\ - font-size: 12px;\n\ - height: 12px;\n\ - width: 30px;\n\ - margin: 1px 0;\n\ -}\n\ -.summary {\n\ - text-decoration: none;\n\ -}\n\ -/* Catalog */\n\ -:root.catalog-mode .board {\n\ - text-align: center;\n\ -}\n\ -.catalog-thread {\n\ - display: inline-block;\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - border: 1px solid transparent;\n\ - word-wrap: break-word;\n\ - vertical-align: top;\n\ - position: relative;\n\ -}\n\ -/* overrides 4chan CSS on div.thread */\n\ -.catalog-thread.catalog-thread {\n\ - margin: 2px;\n\ -}\n\ -.catalog-small > .catalog-thread {\n\ - width: 165px;\n\ - height: 320px;\n\ -}\n\ -.catalog-large > .catalog-thread {\n\ - width: 270px;\n\ - height: 410px;\n\ -}\n\ -:root.catalog-hover-expand .catalog-thread:hover {\n\ - z-index: 1;\n\ -}\n\ -.catalog-container {\n\ - position: absolute;\n\ - top: -4px;\n\ - left: 0;\n\ - right: 0;\n\ - bottom: 0;\n\ -}\n\ -.catalog-container:not(:hover),\n\ -:root:not(.catalog-hover-expand) .catalog-container {\n\ - overflow: hidden;\n\ -}\n\ -.catalog-post {\n\ - position: absolute;\n\ - top: 4px;\n\ - left: 0;\n\ - right: 0;\n\ - border: 1px solid transparent;\n\ - padding-top: 20px;\n\ -}\n\ -/* overrides inline CSS from Index.cb.hoverAdjust */\n\ -:root:not(.catalog-hover-expand) .catalog-post {\n\ - left: 0 !important;\n\ - right: 0 !important;\n\ -}\n\ -/* overrides 4chan CSS on div.post */\n\ -.catalog-post.catalog-post {\n\ - margin: -21px -1px -1px;\n\ - overflow: visible;\n\ -}\n\ -.catalog-thread.noFile > * > .catalog-post {\n\ - margin-top: -7px;\n\ - padding-top: 6px;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover > .catalog-post {\n\ - margin-left: -61px;\n\ - margin-right: -61px;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover > * > :not(.catalog-replies) {\n\ - padding-left: 2px;\n\ - padding-right: 2px;\n\ -}\n\ -.catalog-link {\n\ - display: block;\n\ - position: relative;\n\ -}\n\ -.catalog-thumb {\n\ - border-radius: 2px;\n\ - box-shadow: 0 0 5px rgba(0, 0, 0, .25);\n\ - vertical-align: top;\n\ -}\n\ -.catalog-thumb.spoiler-file {\n\ - width: 100px;\n\ - height: 100px;\n\ -}\n\ -.catalog-thumb.deleted-file {\n\ - width: 127px;\n\ - height: 13px;\n\ - padding: 20px 11px;\n\ -}\n\ -.catalog-thumb.no-file {\n\ - width: 77px;\n\ - height: 13px;\n\ - padding: 20px 36px;\n\ -}\n\ -.catalog-icons > img,\n\ -.catalog-stats > .menu-button {\n\ - width: 1em;\n\ - height: 1em;\n\ - margin: 0;\n\ - vertical-align: text-top;\n\ - padding-left: 2px;\n\ -}\n\ -.catalog-stats > .menu-button {\n\ - font-weight: normal;\n\ -}\n\ -.catalog-stats > .menu-button > i::before {\n\ - line-height: 11px;\n\ -}\n\ -.catalog-stats {\n\ - font-size: 10px;\n\ - font-weight: 700;\n\ - padding-top: 2px;\n\ -}\n\ -.catalog-stats > [title] {\n\ - cursor: help;\n\ -}\n\ -.catalog-post > .postMessage {\n\ - margin: 0;\n\ - padding-bottom: .3em;\n\ -}\n\ -.catalog-container:not(:hover) > * > .file,\n\ -.catalog-container:not(:hover) > * > .postInfo > :not(.subject),\n\ -.catalog-container:not(:hover) > * > .catalog-replies,\n\ -.catalog-container:not(:hover) .extra-linebreak,\n\ -.catalog-container:not(:hover) .abbr,\n\ -:root:not(.catalog-hover-expand) .catalog-container > * > .file,\n\ -:root:not(.catalog-hover-expand) .catalog-container > * > .postInfo > :not(.subject),\n\ -:root:not(.catalog-hover-expand) .catalog-container > * > .catalog-replies,\n\ -:root:not(.catalog-hover-expand) .catalog-container .extra-linebreak,\n\ -:root:not(.catalog-hover-expand) .catalog-container .abbr,\n\ -.catalog-thread > .catalog-container > :not(.catalog-post),\n\ -.catalog-post > .file > :not(.fileText),\n\ -.catalog-post > * > .fileText > :not(:first-child),\n\ -.catalog-post > .postInfo > :not(.subject):not(.nameBlock):not(.dateTime),\n\ -.catalog-post > .postInfo > .nameBlock > .contact-links,\n\ -.catalog-post > * > * > .posteruid,\n\ -.catalog-post > * > * > .postJumper,\n\ -:root.bottom-backlinks .catalog-post > .container,\n\ -.post:not(.catalog-post) > .catalog-link,\n\ -.post:not(.catalog-post) > .catalog-stats,\n\ -.post:not(.catalog-post) > .catalog-replies {\n\ - display: none;\n\ -}\n\ -.catalog-post > .file {\n\ - position: absolute;\n\ - left: 0;\n\ - right: 0;\n\ - top: 0;\n\ - min-height: 20px;\n\ - background-color: inherit;\n\ -}\n\ -.catalog-post > * > .fileText {\n\ - position: relative;\n\ - padding: 2px;\n\ - background-color: inherit;\n\ -}\n\ -.catalog-small .catalog-post > * .fileText {\n\ - font-size: 10px;\n\ -}\n\ -.catalog-post > * > .fileText:not(:hover) {\n\ - white-space: nowrap;\n\ - overflow: hidden;\n\ - text-overflow: ellipsis;\n\ -}\n\ -.catalog-post > * > .fileText:hover {\n\ - z-index: 1;\n\ -}\n\ -/* overrides 4chan CSS on div.post div.postInfo */\n\ -.catalog-post > .postInfo.postInfo {\n\ - width: auto;\n\ -}\n\ -.catalog-post > * > .subject {\n\ - display: block;\n\ -}\n\ -.catalog-post > * > .dateTime {\n\ - display: inline-block;\n\ - font-style: italic;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover > * > * > .nameBlock,\n\ -:root.catalog-hover-expand .catalog-container:hover > * > * > .dateTime,\n\ -:root.catalog-hover-expand .catalog-container:hover > * > .postMessage:not(:empty) {\n\ - padding-top: .3em;\n\ -}\n\ -.catalog-post .extra-linebreak {\n\ - content: ''; /* makes this work in Blink/WebKit */\n\ - display: block;\n\ - margin-top: .3em;\n\ -}\n\ -.catalog-reply {\n\ - text-align: left;\n\ - white-space: nowrap;\n\ - border-top: 1px solid transparent;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ -}\n\ -.catalog-reply > * {\n\ - padding: 3px;\n\ - overflow: hidden;\n\ - -webkit-flex: none;\n\ - flex: none;\n\ -}\n\ -.catalog-reply > span {\n\ - font-style: italic;\n\ - font-weight: bold;\n\ -}\n\ -.catalog-reply-excerpt {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ -}\n\ -.catalog-post .prettyprinted {\n\ - max-width: 100%;\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ -}\n\ -.catalog-post .MathJax_Display {\n\ - text-align: center !important;\n\ -}\n\ -.catalog-container:not(:hover) .exif,\n\ -:root:not(.catalog-hover-expand) .catalog-container .exif {\n\ - display: none !important;\n\ -}\n\ -.catalog-post > * > .exif {\n\ - border-collapse: collapse;\n\ -}\n\ -:root.catalog-hover-expand .catalog-container:hover .exif[style*=\"display: block;\"] {\n\ - display: inline-block !important;\n\ -}\n\ -.catalog-post > * > .exif,\n\ -.catalog-post > * > .exif > tbody {\n\ - background-color: inherit;\n\ -}\n\ -.catalog-post > * > .exif,\n\ -.catalog-post > * > .exif td {\n\ - min-width: 0;\n\ -}\n\ -.catalog-post > * > .exif td {\n\ - padding-top: 1px;\n\ -}\n\ -:root.hats-enabled .catalog-thread::after {\n\ - content: '';\n\ - pointer-events: none;\n\ - position: absolute;\n\ - background-size: contain;\n\ -}\n\ -:root.hats-enabled .catalog-small > .catalog-thread::after {\n\ - left: -8px;\n\ - top: -59px;\n\ - width: 96px;\n\ - height: 96px;\n\ -}\n\ -:root.hats-enabled:not(.werkTyme) .catalog-small > .catalog-thread:not(.noFile)::after {\n\ - left: calc(67px - .3px * var(--tn-w));\n\ -}\n\ -:root.hats-enabled .catalog-large > .catalog-thread::after {\n\ - left: -15px;\n\ - top: -98px;\n\ - width: 160px;\n\ - height: 160px;\n\ -}\n\ -:root.hats-enabled:not(.werkTyme) .catalog-large > .catalog-thread:not(.noFile)::after {\n\ - left: calc(110px - .5px * var(--tn-w));\n\ -}\n\ -/* Copy Text Link's textarea element */\n\ -textarea.copy-text-element {\n\ - height: 0;\n\ - width: 0;\n\ - position: absolute;\n\ - top: -10000px;\n\ -}\n\ -/* Announcement Hiding */\n\ -:root.hide-announcement $site$psa {\n\ - display: none;\n\ -}\n\ -.hide-announcement-button {\n\ - opacity: 0.4;\n\ - float: left;\n\ -}\n\ -/* Unread */\n\ -.unread-line {\n\ - margin: 0;\n\ - border-color: rgb(255,0,0);\n\ -}\n\ -.unread-line + br {\n\ - display: none;\n\ -}\n\ -.unread-mark-read {\n\ - float: right;\n\ - clear: both;\n\ - width: 100%;\n\ - text-align: right;\n\ -}\n\ -:not(.unread-thread) > .unread-mark-read {\n\ - display: none;\n\ -}\n\ -/* Thread Updater */\n\ -#updater {\n\ - background: none;\n\ - border: none;\n\ - box-shadow: none;\n\ -}\n\ -#updater > .move {\n\ - position: absolute;\n\ - top: -5px;\n\ - bottom: -5px;\n\ - left: -5px;\n\ - right: -5px;\n\ - z-index: -1;\n\ -}\n\ -#updater > div:last-child {\n\ - text-align: center;\n\ -}\n\ -#updater input[type=\"number\"] {\n\ - width: 4em;\n\ -}\n\ -:root.float #updater {\n\ - padding: 0px 3px;\n\ -}\n\ -:root:not(.float).shortcut-icons #updater {\n\ - display: inline-block;\n\ - min-width: 12pt;\n\ - text-align: right;\n\ -}\n\ -.new {\n\ - color: limegreen;\n\ -}\n\ -#update-status:not(.empty) + #update-timer:not(.empty):not(.loading) {\n\ - margin-left: 5px;\n\ -}\n\ -#update-timer {\n\ - cursor: pointer;\n\ -}\n\ -/* Thread Watcher */\n\ -#thread-watcher {\n\ - position: absolute;\n\ -}\n\ -#thread-watcher {\n\ - padding-bottom: 3px;\n\ - padding-left: 3px;\n\ - white-space: nowrap;\n\ - min-width: 146px;\n\ -}\n\ -#watched-threads {\n\ - overflow-x: hidden;\n\ - overflow-y: auto;\n\ -}\n\ -#thread-watcher .refresh {\n\ - padding: 0px 3px;\n\ -}\n\ -:root.fixed-watcher #thread-watcher {\n\ - position: fixed;\n\ -}\n\ -:root.fixed-watcher #watched-threads {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 85vh;\n\ - max-height: calc(100vh - 75px);\n\ -}\n\ -:root:not(.fixed-watcher) #watched-threads:not(:hover) {\n\ - max-height: 210px;\n\ - overflow-y: hidden;\n\ -}\n\ -#thread-watcher > .move {\n\ - padding-top: 3px;\n\ -}\n\ -#watched-threads > div {\n\ - padding-left: 3px;\n\ - padding-right: 3px;\n\ -}\n\ -#watched-threads .watcher-link {\n\ - max-width: 250px;\n\ - display: -webkit-inline-flex;\n\ - display: inline-flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ -}\n\ -#watched-threads .watcher-page,\n\ -#watched-threads .watcher-unread {\n\ - -webkit-flex: 0 0 auto;\n\ - flex: 0 0 auto;\n\ - margin-right: 2px;\n\ -}\n\ -#watched-threads .watcher-title {\n\ - overflow: hidden;\n\ - text-overflow: ellipsis;\n\ - -webkit-flex: 0 1 auto;\n\ - flex: 0 1 auto;\n\ -}\n\ -#watched-threads .watcher-title:not(:first-child) {\n\ - margin-left: 2px;\n\ -}\n\ -.replies-quoting-you > a, #watcher-link.replies-quoting-you, .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -#thread-watcher a {\n\ - text-decoration: none;\n\ -}\n\ -#thread-watcher .move > .close {\n\ - position: absolute;\n\ - right: 0px;\n\ - top: 0px;\n\ - padding: 0px 4px;\n\ -}\n\ -.watch-thread-link {\n\ - padding-top: 18px;\n\ - width: 18px;\n\ - height: 0px;\n\ - display: inline-block;\n\ - background-repeat: no-repeat;\n\ - opacity: 0.2;\n\ - position: relative;\n\ - top: 1px;\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -.watch-thread-link.watched {\n\ - opacity: 1;\n\ -}\n\ -/* Thread Stats */\n\ -#thread-stats {\n\ - background: none;\n\ - border: none;\n\ - box-shadow: none;\n\ -}\n\ -:root.float #thread-stats > .move > :not(#page-count) {\n\ - pointer-events: none;\n\ -}\n\ -:root.float #thread-stats {\n\ - padding: 0px 3px;\n\ -}\n\ -#page-count {\n\ - cursor: pointer;\n\ -}\n\ -/* Quote */\n\ -.hashlink::before {\n\ - content: ' ';\n\ - visibility: hidden;\n\ -}\n\ -.inline + .hashlink {\n\ - display: none !important;\n\ -}\n\ -:root.resurrect-quotes .deadlink {\n\ - text-decoration: none !important;\n\ -}\n\ -.catalog-post .qmark-ct {\n\ - display: none;\n\ -}\n\ -.backlink.deadlink:not(.forwardlink),\n\ -.quotelink.deadlink:not(.forwardlink) {\n\ - text-decoration: underline !important;\n\ -}\n\ -:root:not(.catalog-mode) .inlined {\n\ - opacity: .5;\n\ -}\n\ -#qp input, .forwarded {\n\ - display: none;\n\ -}\n\ -.quotelink.forwardlink,\n\ -.backlink.forwardlink {\n\ - text-decoration: none;\n\ - border-bottom: 1px dashed;\n\ -}\n\ -.filtered {\n\ - text-decoration: underline line-through;\n\ -}\n\ -:root.hide-backlinks .backlink.filtered,\n\ -:root.hide-backlinks .backlink.filtered + .hashlink.filtered {\n\ - display: none;\n\ -}\n\ -.postNum + .container::before {\n\ - content: \" \";\n\ -}\n\ -:root.bottom-backlinks .container {\n\ - display: block;\n\ - clear: both;\n\ - margin: 0 4px;\n\ -}\n\ -:root.bottom-backlinks .backlink {\n\ - font-size: 90%;\n\ -}\n\ -.inline {\n\ - border: 1px solid;\n\ - display: table;\n\ - margin: 2px 0;\n\ -}\n\ -.container ~ .inline {\n\ - margin-left: 20px;\n\ -}\n\ -:root.catalog-mode .inline {\n\ - display: none;\n\ -}\n\ -.inline .post {\n\ - border: 0 !important;\n\ - background-color: transparent !important;\n\ - display: table !important;\n\ - margin: 0 !important;\n\ - padding: 1px 2px !important;\n\ -}\n\ -#qp > .opContainer::after {\n\ - content: '';\n\ - clear: both;\n\ - display: table;\n\ -}\n\ -#qp .post {\n\ - border: none;\n\ - margin: 0;\n\ - padding: 2px 2px 5px;\n\ -}\n\ -#qp img {\n\ - max-height: 80vh;\n\ - max-width: 50vw;\n\ -}\n\ -/* Quote Threading */\n\ -.threadContainer {\n\ - margin-left: 20px;\n\ - border-left: 1px solid rgba(128,128,128,.3);\n\ -}\n\ -.threadOP {\n\ - clear: both;\n\ -}\n\ -/* File */\n\ -.fileText-original,\n\ -.fnswitch:hover > .fntrunc,\n\ -.fnswitch:not(:hover) > .fnfull,\n\ -.expanded-image > .post > .file > .fileThumb > video[data-md5],\n\ -.expanded-image > .post > .file > .fileThumb > img[data-md5] {\n\ - display: none;\n\ -}\n\ -.full-image[data-file-i-d] {\n\ - display: none;\n\ - cursor: pointer;\n\ -}\n\ -.expanded-image > .post > .file > .fileThumb > .full-image {\n\ - display: inline;\n\ -}\n\ -.expanded-image {\n\ - clear: left;\n\ -}\n\ -.expanding {\n\ - opacity: .5;\n\ -}\n\ -:root.fit-height .full-image {\n\ - max-height: 100vh;\n\ -}\n\ -:root.fit-height.fixed .full-image {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 93vh;\n\ - max-height: calc(100vh - 35px);\n\ -}\n\ -:root.fit-width .full-image {\n\ - max-width: 100%;\n\ -}\n\ -:root.ua-gecko.fit-width .full-image {\n\ - width: 100%;\n\ -}\n\ -.fileThumb > .warning {\n\ - clear: both;\n\ -}\n\ -#ihover {\n\ - pointer-events: none;\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 95vh;\n\ - max-height: calc(100vh - 25px);\n\ - max-width: 100vw;\n\ -}\n\ -/* WEBM Metadata */\n\ -.webm-title > a::before {\n\ - content: \"title\";\n\ - text-decoration: underline;\n\ -}\n\ -.webm-title.loading > a::after {\n\ - content: \"...\";\n\ -}\n\ -.webm-title.error > a:hover::before,\n\ -.webm-title.error > a:focus::before {\n\ - content: \"error\";\n\ - text-decoration: none;\n\ -}\n\ -.webm-title > span {\n\ - cursor: text;\n\ -}\n\ -.webm-title.not-found > span::before {\n\ - content: \"not found\";\n\ -}\n\ -.webm-title:not(:hover):not(:focus) > span,\n\ -.webm-title:hover > span + a,\n\ -.webm-title:focus > span + a {\n\ - display: none;\n\ -}\n\ -/* Volume control */\n\ -input[name=\"Default Volume\"] {\n\ - width: 4em;\n\ - height: 1ex;\n\ - vertical-align: middle;\n\ - margin: 0px;\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.fappeTyme $site$replyOriginal.noFile,\n\ -:root.fappeTyme $site$replyOriginal.noFile + br {\n\ - display: none;\n\ -}\n\ -:root.werkTyme $site$thumbLink,\n\ -:root.werkTyme $site$file$thumb,\n\ -:root.werkTyme .catalog-thumb:not(.deleted-file):not(.no-file),\n\ -:root:not(.werkTyme) .werkTyme-filename {\n\ - display: none;\n\ -}\n\ -.werkTyme-filename {\n\ - font-weight: bold;\n\ - font-size: 110%;\n\ -}\n\ -:root.werkTyme .catalog-link {\n\ - box-shadow: 0 0 5px rgba(0, 0, 0, .25);\n\ - padding: 8px;\n\ - text-align: center;\n\ -}\n\ -:root.werkTyme .catalog-thumb {\n\ - box-shadow: none;\n\ - padding: 0;\n\ - vertical-align: middle;\n\ -}\n\ -.indicator {\n\ - background: rgba(255,0,0,0.8);\n\ - font-weight: bold;\n\ - display: inline-block;\n\ - min-width: 9px;\n\ - padding: 0px 2px;\n\ - margin: 0 1px;\n\ - text-align: center;\n\ - color: white;\n\ - border-radius: 2px;\n\ - cursor: pointer;\n\ -}\n\ -:root:not(.fappeTyme) #shortcut-fappe,\n\ -:root:not(.werkTyme) #shortcut-werk {\n\ - display: none;\n\ -}\n\ -/* Index/Reply Navigation */\n\ -#navlinks {\n\ - font-size: 16px;\n\ - top: 25px;\n\ - right: 10px;\n\ -}\n\ -:root.catalog-mode #navlinks {\n\ - display: none;\n\ -}\n\ -/* Highlighting */\n\ -.qphl {\n\ - outline: 2px solid rgba(216, 94, 49, .8);\n\ -}\n\ -:root.highlight-you .quotesYou$site$highlightable$op,\n\ -:root.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8);\n\ -}\n\ -:root.highlight-own .yourPost$site$highlightable$op,\n\ -:root.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8);\n\ -}\n\ -.filter-highlight$site$highlightable$op,\n\ -.filter-highlight$site$highlightable$reply {\n\ - box-shadow: inset 5px 0 rgba(221, 0, 0, .5);\n\ -}\n\ -:root.highlight-own .yourPost > $site$sideArrows,\n\ -:root.highlight-you .quotesYou > $site$sideArrows,\n\ -.filter-highlight > $site$sideArrows {\n\ - color: rgba(221, 0, 0, .8);\n\ -}\n\ -:root.highlight-own .yourPost$site$highlightable$op::after,\n\ -:root.highlight-you .quotesYou$site$highlightable$op::after,\n\ -.filter-highlight$site$highlightable$op::after {\n\ - content: \"\";\n\ - display: block;\n\ - clear: both;\n\ -}\n\ -:root:not(.werkTyme) .catalog-thread.filter-highlight .catalog-thumb,\n\ -:root.werkTyme .catalog-thread.filter-highlight:not(:hover),\n\ -:root.werkTyme:not(.catalog-hover-expand) .catalog-thread.filter-highlight,\n\ -:root.werkTyme.catalog-hover-expand .catalog-thread.filter-highlight > .catalog-container:hover > .catalog-post,\n\ -:root.catalog $site$catalog$thread.filter-highlight$site$highlightable$catalog {\n\ - box-shadow: 0 0 3px 3px rgba(255, 0, 0, .5);\n\ -}\n\ -:root:not(.werkTyme) .catalog-thread.watched .catalog-thumb,\n\ -:root:root.werkTyme .catalog-thread.watched:not(:hover),\n\ -:root:root.werkTyme:not(.catalog-hover-expand) .catalog-thread.watched,\n\ -:root.werkTyme.catalog-hover-expand .catalog-thread.watched > .catalog-container:hover > .catalog-post {\n\ - border: 2px solid rgba(255, 0, 0, .75);\n\ -}\n\ -/* Spoiler text */\n\ -:root.reveal-spoilers $site$spoiler,\n\ -:root.reveal-spoilers $site$spoiler > a {\n\ - color: white !important;\n\ -}\n\ -:root.reveal-spoilers .removed-spoiler::before {\n\ - content: \"[spoiler]\";\n\ -}\n\ -:root.reveal-spoilers .removed-spoiler::after {\n\ - content: \"[/spoiler]\";\n\ -}\n\ -/* Thread & Reply Hiding */\n\ -.hide-thread-button,\n\ -.hide-reply-button {\n\ - float: left;\n\ - margin-right: 4px;\n\ - padding: 2px;\n\ -}\n\ -$site$infoRoot a.hide-reply-button {\n\ - margin-right: 6px;\n\ - padding: 0;\n\ -}\n\ -.replacedSideArrows {\n\ - float: left;\n\ -}\n\ -.hide-thread-button:not(:hover),\n\ -.hide-reply-button:not(:hover) {\n\ - opacity: 0.4;\n\ -}\n\ -.threadContainer .hide-reply-button {\n\ - margin-left: 2px !important;\n\ - position: relative;\n\ - left: 1px;\n\ -}\n\ -.hide-thread-button {\n\ - margin-top: -1px;\n\ - width: 11px;\n\ -}\n\ -.stub ~ :not(.threadDivider) {\n\ - display: none !important;\n\ -}\n\ -.stub input {\n\ - display: inline-block;\n\ -}\n\ -$site$thread[hidden] + hr {\n\ - display: none;\n\ -}\n\ -:root.reply-hide $site$sideArrows {\n\ - display: none;\n\ -}\n\ -:root.sw-yotsuba.thread-hide .party-hat {\n\ - left: 19px;\n\ -}\n\ -/* Anonymize */\n\ -:root.anonymize $site$info$name,\n\ -:root.sw-yotsuba.anonymize .post-author:not([class*=capcode]) {\n\ - font-size: 0;\n\ -}\n\ -:root.anonymize $site$info$tripcode,\n\ -:root.sw-yotsuba.anonymize .n-pu {\n\ - display: none;\n\ -}\n\ -:root.anonymize $site$info$name::before,\n\ -:root.sw-yotsuba.anonymize .post-author:not([class*=capcode])::before {\n\ - content: \"Anonymous\";\n\ - font-size: 10pt;\n\ -}\n\ -:root.sw-yotsuba.anonymize .flashListing .name::before,\n\ -:root.sw-yotsuba.anonymize .post-last > .post-author:not([class*=capcode])::before {\n\ - font-size: 9pt;\n\ -}\n\ -/* QR */\n\ -:root.hide-original-post-form #togglePostFormLink,\n\ -#qr.autohide:not(.focus):not(:hover):not(:active) > form,\n\ -:root.thread-view #qr:not(.show-new-thread-option) select[data-name=\"thread\"],\n\ -#file-n-submit:not(.has-file) #qr-filerm {\n\ - display: none;\n\ -}\n\ -:root.hide-original-post-form #postForm {\n\ - display: none !important;\n\ -}\n\ -#qr select,\n\ -#qr-filename-container > a,\n\ -.remove,\n\ -.captcha-img {\n\ - cursor: pointer;\n\ -}\n\ -#qr {\n\ - position: fixed;\n\ - padding: 1px;\n\ - border: 1px solid transparent;\n\ - min-width: 300px;\n\ - border-radius: 3px 3px 0 0;\n\ -}\n\ -#qr > form {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 85vh;\n\ - max-height: calc(100vh - 75px);\n\ - overflow-y: auto;\n\ - overflow-x: hidden;\n\ -}\n\ -#qrtab {\n\ - border-radius: 3px 3px 0 0;\n\ -}\n\ -#qrtab {\n\ - margin-bottom: 1px;\n\ -}\n\ -#qr .close {\n\ - float: right;\n\ - padding: 0 3px;\n\ -}\n\ -.qr-link-container {\n\ - text-align: center;\n\ - margin: 16px 0;\n\ -}\n\ -.qr-link-container-bottom {\n\ - width: 200px;\n\ - position: absolute;\n\ - left: -100px;\n\ - margin-left: 50%;\n\ - text-align: center;\n\ -}\n\ -.qr-link {\n\ - border-radius: 3px;\n\ - padding: 6px 10px 5px;\n\ - font-weight: bold;\n\ - vertical-align: middle;\n\ - border-style: solid;\n\ - border-width: 1px;\n\ - font-size: 10pt;\n\ -}\n\ -.qr-link-container + #togglePostFormLink {\n\ - font-size: 10pt;\n\ - font-weight: normal;\n\ - margin: -8px 0 3.5px;\n\ -}\n\ -.persona {\n\ - width: 100%;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ -}\n\ -.persona .field {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ - width: 0;\n\ -}\n\ -#qr.forced-anon input[data-name=\"name\"]:not(.force-show),\n\ -#qr.forced-anon input[data-name=\"sub\"]:not(.force-show),\n\ -#qr.reply-to-thread input[data-name=\"sub\"]:not(.force-show),\n\ -body:not(.board_f) #qr select[name=\"filetag\"],\n\ -#qr.reply-to-thread select[name=\"filetag\"],\n\ -#qr:not(.has-sjis) #sjis-toggle,\n\ -#qr:not(.has-math) #tex-preview-button,\n\ -#qr.tex-preview .textarea > :not(#tex-preview),\n\ -#qr:not(.tex-preview) #tex-preview {\n\ - display: none;\n\ -}\n\ -.persona button {\n\ - -webkit-flex: 0 0 23px;\n\ - flex: 0 0 23px;\n\ - -webkit-align-self: stretch;\n\ - align-self: stretch;\n\ - border: 1px solid #BBB;\n\ - padding: 0;\n\ - background: linear-gradient(to bottom, #F8F8F8, #DCDCDC) no-repeat;\n\ - color: #000;\n\ -}\n\ -#qr.sjis-preview #sjis-toggle, #qr.tex-preview #tex-preview-button {\n\ - background: #DCDCDC;\n\ -}\n\ -#sjis-toggle, #qr.sjis-preview textarea.field {\n\ - font-family: \"IPAMonaPGothic\",\"Mona\",\"MS PGothic\",monospace;\n\ - font-size: 16px;\n\ - line-height: 17px;\n\ -}\n\ -#tex-preview-button {\n\ - font-size: 10px;\n\ -}\n\ -#tex-preview {\n\ - white-space: pre-line;\n\ -}\n\ -#qr textarea.field {\n\ - height: 14.8em;\n\ - min-height: 9em;\n\ -}\n\ -#qr.has-captcha textarea.field {\n\ - height: 9em;\n\ -}\n\ -input.field.tripped:not(:hover):not(:focus) {\n\ - color: transparent !important;\n\ - text-shadow: none !important;\n\ -}\n\ -#qr textarea {\n\ - min-width: 300px;\n\ - resize: both;\n\ -}\n\ -.field {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - margin: 0px;\n\ - padding: 2px 4px 3px;\n\ -}\n\ -#qr label input[type=\"checkbox\"] {\n\ - position: relative;\n\ - top: 2px;\n\ -}\n\ -/* Recaptcha v2 */\n\ -#qr .captcha-root {\n\ - position: relative;\n\ -}\n\ -#qr .captcha-container > div {\n\ - margin: auto;\n\ - width: 304px;\n\ -}\n\ -/* XXX scrollable with scroll bar hidden; prevents scroll on space press */\n\ -:root.ua-blink #qr .captcha-container > div,\n\ -:root.ua-edge #qr .captcha-container > div {\n\ - overflow: hidden;\n\ -}\n\ -:root.ua-blink #qr .captcha-container > div > div:first-of-type,\n\ -:root.ua-edge #qr .captcha-container > div > div:first-of-type {\n\ - overflow-y: scroll;\n\ - overflow-x: hidden;\n\ - padding-right: 30px;\n\ - height: 99%;\n\ - width: 100%;\n\ -}\n\ -#qr .captcha-counter {\n\ - display: block;\n\ - width: 100%;\n\ - text-align: center;\n\ - pointer-events: none;\n\ -}\n\ -#qr.captcha-open .captcha-counter {\n\ - position: absolute;\n\ - bottom: 3px;\n\ -}\n\ -#qr .captcha-counter > a {\n\ - pointer-events: auto;\n\ - display: inline-block; /* XXX https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8851747/ */\n\ -}\n\ -#qr:not(.captcha-open) .captcha-counter > a {\n\ - display: block;\n\ - width: 100%;\n\ -}\n\ -#qr.captcha-v2 #qr-captcha-iframe {\n\ - width: 302px;\n\ - height: 423px;\n\ - border: 0;\n\ - display: block;\n\ - margin: auto;\n\ -}\n\ -.goog-bubble-content {\n\ - max-width: 100vw;\n\ - max-height: 100vh;\n\ - overflow: auto;\n\ -}\n\ -.goog-bubble-content iframe {\n\ - position: static !important;\n\ -}\n\ -/* File Input, Submit Button, Oekaki */\n\ -#file-n-submit, #qr .oekaki {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ - height: 25px;\n\ - margin-top: 1px;\n\ -}\n\ -#file-n-submit > input, #qr-draw-button {\n\ - background: linear-gradient(to bottom, #F8F8F8, #DCDCDC) no-repeat;\n\ - border: 1px solid #BBB;\n\ - border-radius: 2px;\n\ - height: 100%;\n\ -}\n\ -#qr-file-button, #qr-draw-button {\n\ - width: 15%;\n\ -}\n\ -#file-n-submit input[type=\"submit\"] {\n\ - width: 25%;\n\ -}\n\ -#qr-filename-container {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - position: relative;\n\ - padding: 1px;\n\ -}\n\ -input#qr-filename {\n\ - border: none !important;\n\ - background: none !important;\n\ - outline: none;\n\ -}\n\ -#qr-filename,\n\ -.has-file #qr-no-file {\n\ - display: none;\n\ -}\n\ -#qr-no-file,\n\ -.has-file #qr-filename {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0px; /* XXX Fixes filename not shrinking to allow space for buttons in Edge */\n\ - display: inline-block;\n\ - padding: 0;\n\ - padding-left: 3px;\n\ - overflow: hidden;\n\ - text-overflow: ellipsis;\n\ - white-space: nowrap;\n\ -}\n\ -#qr-no-file {\n\ - color: #AAA;\n\ -}\n\ -#qr .oekaki.has-file {\n\ - display: none;\n\ -}\n\ -#qr .oekaki > label {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: center;\n\ - align-items: center;\n\ - height: 100%;\n\ -}\n\ -#qr .oekaki > label > span {\n\ - margin: 0 3px;\n\ -}\n\ -#qr .oekaki > label > input {\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - width: 0;\n\ - height: 100%;\n\ -}\n\ -#qr .oekaki-bg {\n\ - position: relative;\n\ - display: inline-block;\n\ - height: 100%;\n\ - width: 10%;\n\ - margin-left: 3px;\n\ -}\n\ -#qr .oekaki-bg > * {\n\ - position: absolute;\n\ - top: 0;\n\ - left: 0;\n\ - margin: 0;\n\ -}\n\ -#qr .oekaki-bg > :not([name=\"oekaki-bgcolor\"]) {\n\ - z-index: 1;\n\ -}\n\ -#qr [name=\"oekaki-bgcolor\"] {\n\ - height: 100%;\n\ - width: 100%;\n\ - border: none;\n\ - padding: 0;\n\ -}\n\ -#qr [name=\"oekaki-bg\"]:not(:checked) ~ [name=\"oekaki-bgcolor\"] {\n\ - visibility: hidden;\n\ -}\n\ -#qr input[type=\"file\"] {\n\ - visibility: hidden;\n\ - position: absolute;\n\ -}\n\ -/* Spoiler Checkbox, QR Icons */\n\ -#qr-filename-container > label, #qr-filename-container > a {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ - margin: 0;\n\ - margin-right: 3px;\n\ -}\n\ -#qr:not(.has-spoiler) #qr-spoiler-label,\n\ -#file-n-submit:not(.has-file) #qr-spoiler-label,\n\ -.has-file #paste-area,\n\ -.has-file #url-button,\n\ -#file-n-submit:not(.custom-cooldown) #custom-cooldown-button {\n\ - display: none;\n\ -}\n\ -#qr-filename-container > label {\n\ - position: relative;\n\ -}\n\ -#qr-filename-container input[type=\"checkbox\"] {\n\ - margin: 0;\n\ -}\n\ -.checkbox-letter {\n\ - font-size: 13px;\n\ - font-weight: bold;\n\ -}\n\ -#qr-filename-container label:not(:hover) > input[type=\"checkbox\"]:not(:focus):not(:checked),\n\ -#qr-filename-container label:not(:hover) > input[type=\"checkbox\"]:not(:focus):not(:checked) ~ :not(.checkbox-letter),\n\ -#qr-filename-container label:hover > .checkbox-letter,\n\ -input[type=\"checkbox\"]:focus ~ .checkbox-letter,\n\ -input[type=\"checkbox\"]:checked ~ .checkbox-letter {\n\ - /* not displayed but still focusable */\n\ - position: absolute;\n\ - opacity: 0;\n\ - pointer-events: none;\n\ -}\n\ -.checkbox-letter, #paste-area, #url-button, #custom-cooldown-button, #dump-button {\n\ - opacity: 0.6;\n\ -}\n\ -#paste-area {\n\ - font-size: 0;\n\ -}\n\ -#paste-area:focus {\n\ - opacity: 1;\n\ -}\n\ -#custom-cooldown-button.disabled {\n\ - opacity: 0.27;\n\ -}\n\ -/* Thread and Flash Tag Select */\n\ -#qr select {\n\ - background: white;\n\ - border: 1px solid #CCC;\n\ -}\n\ -#qr select[data-name=\"thread\"] {\n\ - float: right;\n\ -}\n\ -#qr > form > select {\n\ - margin-top: 1px;\n\ -}\n\ -/* Dumping UI */\n\ -.dump #dump-list-container {\n\ - display: block;\n\ -}\n\ -#dump-list-container {\n\ - display: none;\n\ - position: relative;\n\ - overflow-y: hidden;\n\ - margin-top: 1px;\n\ -}\n\ -#dump-list {\n\ - overflow-x: auto;\n\ - overflow-y: auto;\n\ - white-space: nowrap;\n\ - width: 248px;\n\ - max-height: 248px;\n\ - min-height: 90px;\n\ - max-width: 100%;\n\ - min-width: 100%;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-wrap: wrap;\n\ - flex-wrap: wrap;\n\ -}\n\ -#dump-list:hover {\n\ - overflow-x: auto;\n\ -}\n\ -.qr-preview {\n\ - -moz-box-sizing: border-box;\n\ - box-sizing: border-box;\n\ - counter-increment: thumbnails;\n\ - cursor: move;\n\ - display: inline-block;\n\ - height: 90px;\n\ - width: 90px;\n\ - padding: 2px;\n\ - opacity: .5;\n\ - overflow: hidden;\n\ - position: relative;\n\ - text-shadow: 0 0 2px #000;\n\ - -webkit-transition: opacity .25s ease-in-out, -webkit-transform .25s ease-in-out;\n\ - transition: opacity .25s ease-in-out, transform .25s ease-in-out, -webkit-transform .25s ease-in-out;\n\ - vertical-align: top;\n\ - background-size: cover;\n\ - -webkit-flex: none;\n\ - flex: none;\n\ -}\n\ -.qr-preview:hover,\n\ -.qr-preview:focus {\n\ - opacity: .9;\n\ -}\n\ -.qr-preview::before {\n\ - content: counter(thumbnails);\n\ - color: #fff;\n\ - position: absolute;\n\ - top: 3px;\n\ - right: 3px;\n\ - text-shadow: 0 0 3px #000, 0 0 8px #000;\n\ -}\n\ -.qr-preview#selected {\n\ - opacity: 1;\n\ -}\n\ -.qr-preview.drag {\n\ - box-shadow: 0 0 10px rgba(0,0,0,.5);\n\ - -webkit-transform: scale(.8);\n\ - transform: scale(.8);\n\ -}\n\ -.qr-preview.over {\n\ - border-color: #fff;\n\ - -webkit-transform: scale(1.1);\n\ - transform: scale(1.1);\n\ - opacity: 0.9;\n\ - z-index: 10;\n\ -}\n\ -.qr-preview > span {\n\ - color: #fff;\n\ -}\n\ -.remove {\n\ - background: none;\n\ - color: #e00;\n\ - padding: 1px;\n\ -}\n\ -a:only-of-type > .remove {\n\ - display: none;\n\ -}\n\ -.remove:hover::after {\n\ - content: \" Remove\";\n\ -}\n\ -.qr-preview:not(.has-file) label,\n\ -#qr:not(.has-spoiler) .qr-preview-spoiler {\n\ - display: none;\n\ -}\n\ -.qr-preview > label {\n\ - background: rgba(0,0,0,.5);\n\ - color: #fff;\n\ - right: 0;\n\ - bottom: 0;\n\ - left: 0;\n\ - position: absolute;\n\ - text-align: center;\n\ -}\n\ -.qr-preview > label > input {\n\ - margin: 0;\n\ -}\n\ -#add-post {\n\ - cursor: pointer;\n\ - font-size: 2em;\n\ - position: absolute;\n\ - bottom: 20px;\n\ - right: 10px;\n\ - -webkit-transform: translateY(-50%);\n\ - transform: translateY(-50%);\n\ -}\n\ -.textarea {\n\ - position: relative;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ -}\n\ -#char-count {\n\ - color: #000;\n\ - background: hsla(0, 0%, 100%, .5);\n\ - font-size: 8pt;\n\ - position: absolute;\n\ - bottom: 1px;\n\ - right: 1px;\n\ - pointer-events: none;\n\ -}\n\ -#char-count.warning {\n\ - color: red;\n\ -}\n\ -/* Menu */\n\ -.menu-button:not(.fa-bars) {\n\ - display: inline-block;\n\ - position: relative;\n\ - cursor: pointer;\n\ -}\n\ -#header-bar .menu-button i {\n\ - border-top: 6px solid;\n\ - border-right: 4px solid transparent;\n\ - border-left: 4px solid transparent;\n\ - display: inline-block;\n\ - margin: 2px;\n\ - vertical-align: middle;\n\ -}\n\ -.postInfo > .menu-button,\n\ -#thread-watcher .menu-button {\n\ - width: 18px;\n\ - height: 15px;\n\ - text-align: center;\n\ -}\n\ -#menu {\n\ - position: fixed;\n\ - outline: none;\n\ - font-weight: normal;\n\ -}\n\ -#menu, .submenu {\n\ - border-radius: 3px;\n\ - padding-top: 1px;\n\ - padding-bottom: 3px;\n\ -}\n\ -.entry {\n\ - cursor: pointer;\n\ - display: block;\n\ - outline: none;\n\ - padding: 2px 10px;\n\ - position: relative;\n\ - text-decoration: none;\n\ - white-space: nowrap;\n\ - min-width: 70px;\n\ - text-align: left;\n\ - text-shadow: none;\n\ - font-size: 10pt;\n\ -}\n\ -.left>.entry.has-submenu {\n\ - padding-right: 17px !important;\n\ -}\n\ -.entry input[type=\"checkbox\"],\n\ -.entry input[type=\"radio\"] {\n\ - margin: 0px;\n\ - position: relative;\n\ - top: 2px;\n\ -}\n\ -.entry input[type=\"number\"] {\n\ - width: 4.5em;\n\ -}\n\ -.entry.has-shortcut-text {\n\ - display: flex;\n\ - justify-content: space-between;\n\ - align-items: center;\n\ -}\n\ -.entry .shortcut-text {\n\ - opacity: 0.5;\n\ - font-size: 70%;\n\ - margin-left: 5px;\n\ -}\n\ -.has-submenu::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\ -.left .has-submenu::after {\n\ - border-left: 0;\n\ - border-right: .5em solid;\n\ -}\n\ -.submenu {\n\ - display: none;\n\ - position: absolute;\n\ - left: 100%;\n\ - top: -1px;\n\ - margin-left: 0px;\n\ - margin-top: -2px;\n\ -}\n\ -.focused > .submenu {\n\ - display: block;\n\ -}\n\ -.imp-exp-result {\n\ - position: absolute;\n\ - text-align: center;\n\ - margin: auto;\n\ - right: 0px;\n\ - left: 0px;\n\ - width: 200px;\n\ -}\n\ -/* Custom Board Titles */\n\ -.boardTitle, .boardSubtitle {\n\ - white-space: pre-line;\n\ -}\n\ -.boardTitle[contenteditable=\"true\"],\n\ -.boardSubtitle[contenteditable=\"true\"] {\n\ - cursor: text !important;\n\ -}\n\ -/* Embedding */\n\ -.embedder:not(.embedded) > span {\n\ - display: none;\n\ -}\n\ -#embedding {\n\ - padding: 1px 4px 1px 4px;\n\ - position: fixed;\n\ -}\n\ -#embedding.empty {\n\ - display: none;\n\ -}\n\ -#embedding > div:first-child {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ -}\n\ -#embedding .move {\n\ - -webkit-flex: 1;\n\ - flex: 1;\n\ -}\n\ -#embedding .jump {\n\ - margin: -1px 4px;\n\ - text-decoration: none;\n\ -}\n\ -/* Gallery */\n\ -#a-gallery {\n\ - position: fixed;\n\ - top: 0;\n\ - bottom: 0;\n\ - left: 0;\n\ - right: 0;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ - background: rgba(0,0,0,0.7);\n\ -}\n\ -.gal-viewport {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ - -webkit-flex-direction: row;\n\ - flex-direction: row;\n\ - -webkit-flex: 1 1 auto;\n\ - flex: 1 1 auto;\n\ - overflow: hidden;\n\ -}\n\ -.gal-thumbnails {\n\ - -webkit-flex: 0 0 150px;\n\ - flex: 0 0 150px;\n\ - overflow-y: auto;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: column;\n\ - flex-direction: column;\n\ - -webkit-align-items: stretch;\n\ - align-items: stretch;\n\ - text-align: center;\n\ - background: rgba(0,0,0,.5);\n\ - border-left: 1px solid #222;\n\ -}\n\ -.gal-hide-thumbnails .gal-thumbnails {\n\ - display: none;\n\ -}\n\ -.gal-thumb img,\n\ -.gal-thumb video {\n\ - max-width: 125px;\n\ - max-height: 125px;\n\ - height: auto;\n\ - width: auto;\n\ -}\n\ -.gal-thumb {\n\ - -webkit-flex: 0 0 auto;\n\ - flex: 0 0 auto;\n\ - padding: 3px;\n\ - line-height: 0;\n\ - transition: background .2s linear;\n\ -}\n\ -.gal-highlight {\n\ - background: rgba(0, 190, 255,.8);\n\ -}\n\ -.gal-prev {\n\ - border-right: 1px solid #222;\n\ -}\n\ -.gal-next {\n\ - border-left: 1px solid #222;\n\ -}\n\ -.gal-prev,\n\ -.gal-next {\n\ - -webkit-flex: 0 0 20px;\n\ - flex: 0 0 20px;\n\ - position: relative;\n\ - cursor: pointer;\n\ - opacity: 0.7;\n\ - background-color: rgba(0, 0, 0, 0.3);\n\ -}\n\ -.gal-prev:hover,\n\ -.gal-next:hover {\n\ - opacity: 1;\n\ -}\n\ -.gal-prev::after,\n\ -.gal-next::after {\n\ - position: absolute;\n\ - top: 48.6%;\n\ - -webkit-transform: translateY(-50%);\n\ - transform: translateY(-50%);\n\ - display: inline-block;\n\ - border-top: 11px solid transparent;\n\ - border-bottom: 11px solid transparent;\n\ - content: \"\";\n\ -}\n\ -.gal-prev::after {\n\ - border-right: 12px solid #fff;\n\ - right: 5px;\n\ -}\n\ -.gal-next::after {\n\ - border-left: 12px solid #fff;\n\ - right: 3px;\n\ -}\n\ -.gal-image {\n\ - -webkit-flex: 1 0 auto;\n\ - flex: 1 0 auto;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: flex-start;\n\ - align-items: flex-start;\n\ - -webkit-justify-content: space-around;\n\ - justify-content: space-around;\n\ - overflow: hidden;\n\ - /* Flex > Non-Flex child max-width and overflow fix (Firefox only?) */\n\ - width: 1%;\n\ -}\n\ -:root:not(.gal-fit-height):not(.gal-pdf) .gal-image {\n\ - overflow-y: scroll !important;\n\ -}\n\ -:root:not(.gal-fit-width):not(.gal-pdf) .gal-image {\n\ - overflow-x: scroll !important;\n\ -}\n\ -.gal-image a {\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-align-items: flex-start;\n\ - align-items: flex-start;\n\ - margin: auto;\n\ - line-height: 0;\n\ - max-width: 100%;\n\ -}\n\ -:root.gal-pdf .gal-image a {\n\ - width: 100%;\n\ - height: 100%;\n\ -}\n\ -.gal-image img,\n\ -.gal-image video {\n\ - -webkit-flex: none;\n\ - flex: none;\n\ -}\n\ -.gal-fit-width .gal-image img,\n\ -.gal-fit-width .gal-image video {\n\ - max-width: 100%;\n\ -}\n\ -.gal-fit-height .gal-image img,\n\ -.gal-fit-height .gal-image video {\n\ - /* XXX https://code.google.com/p/chromium/issues/detail?id=168840, https://bugs.webkit.org/show_bug.cgi?id=94158 */\n\ - max-height: 95vh;\n\ - max-height: calc(100vh - 25px);\n\ -}\n\ -.gal-image iframe {\n\ - width: 100%;\n\ - height: 100%;\n\ -}\n\ -.gal-buttons {\n\ - font-size: 2em;\n\ - margin-right: 3px;\n\ - padding-left: 7px;\n\ - padding-right: 7px;\n\ - top: 5px;\n\ -}\n\ -:root.gal-pdf .gal-buttons {\n\ - top: 40px;\n\ - background: rgba(0,0,0,0.6) !important;\n\ - border-radius: 3px;\n\ -}\n\ -.gal-buttons a {\n\ - color: #ffffff;\n\ - text-shadow: 0px 0px 1px #000000;\n\ -}\n\ -.gal-buttons i {\n\ - display: inline-block;\n\ - margin: 2px;\n\ - position: relative;\n\ -}\n\ -.gal-start i {\n\ - border-left: 10px solid;\n\ - border-top: 6px solid transparent;\n\ - border-bottom: 6px solid transparent;\n\ - bottom: 1px;\n\ -}\n\ -.gal-stop i {\n\ - border: 5px solid;\n\ - bottom: 2px;\n\ -}\n\ -.gal-buttons.gal-playing > .gal-start,\n\ -.gal-buttons:not(.gal-playing) > .gal-stop {\n\ - display: none;\n\ -}\n\ -.gal-buttons .menu-button i {\n\ - border-top: 10px solid;\n\ - border-right: 6px solid transparent;\n\ - border-left: 6px solid transparent;\n\ - bottom: 2px;\n\ - vertical-align: baseline;\n\ -}\n\ -.gal-labels {\n\ - position: fixed;\n\ - bottom: 6px;\n\ - display: -webkit-flex;\n\ - display: flex;\n\ - -webkit-flex-direction: column;\n\ - flex-direction: column;\n\ - -webkit-align-items: flex-end;\n\ - align-items: flex-end;\n\ -}\n\ -:root:not(.show-sauce) .gal-sauce {\n\ - display: none;\n\ -}\n\ -.gal-name,\n\ -.gal-count,\n\ -.gal-sauce {\n\ - background: rgba(0,0,0,0.6) !important;\n\ - border-radius: 3px;\n\ - padding: 1px 5px 2px 5px;\n\ - margin-top: 3px;\n\ - color: #ffffff !important;\n\ - text-decoration: none !important;\n\ -}\n\ -.gal-sauce a {\n\ - color: #ffffff !important;\n\ -}\n\ -.gal-name:hover,\n\ -.gal-buttons a:hover,\n\ -.gal-sauce a:hover {\n\ - color: rgb(95, 95, 101) !important;\n\ -}\n\ -:root.gal-pdf .gal-buttons a:hover {\n\ - color: rgb(204, 204, 204) !important;\n\ -}\n\ -.gal-buttons,\n\ -.gal-labels {\n\ - position: fixed;\n\ - right: 195px;\n\ -}\n\ -.gal-hide-thumbnails .gal-buttons,\n\ -.gal-hide-thumbnails .gal-labels {\n\ - right: 44px;\n\ -}\n\ -:root:not(.gal-fit-width):not(.gal-pdf) .gal-labels {\n\ - bottom: 23px !important;\n\ -}\n\ -:root.gal-fit-height:not(.gal-pdf):not(.gal-hide-thumbnails) .gal-buttons,\n\ -:root.gal-fit-height:not(.gal-pdf):not(.gal-hide-thumbnails) .gal-labels {\n\ - right: 178px !important;\n\ -}\n\ -:root.gal-hide-thumbnails.gal-fit-height:not(.gal-pdf) .gal-buttons,\n\ -:root.gal-hide-thumbnails.gal-fit-height:not(.gal-pdf) .gal-labels {\n\ - right: 28px !important;\n\ -}\n\ -:root.gallery-open.fixed #header-bar:not(.autohide),\n\ -:root.gallery-open.fixed #header-bar:not(.autohide) #shortcuts .fa::before {\n\ - visibility: hidden;\n\ -}\n\ -/* Mod Contact Links */\n\ -.contact-links {\n\ - margin-left: 2px;\n\ -}\n\ -.move-note > a {\n\ - text-decoration: underline;\n\ -}\n\ -.invisible {\n\ - font-size: 0;\n\ -}\n\ -/* PostJumper */\n\ -.postJumper > .prev,\n\ -.postJumper > .next {\n\ - font-size: 120%;\n\ -}\n\ -/* PSA */\n\ -.fcx-announcement {\n\ - text-align: center;\n\ -}\n\ -.fcx-announcement a {\n\ - text-decoration: underline;\n\ -}\n\ -/* General */\n\ -:root.yotsuba .dialog {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.yotsuba .field:focus,\n\ -:root.yotsuba .field.focus {\n\ - border-color: #EA8;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.yotsuba.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8) !important;\n\ -}\n\ -:root.yotsuba.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.yotsuba #header-bar.dialog {\n\ - background-color: rgba(240,224,214,0.98);\n\ -}\n\ -:root.yotsuba:not(.fixed) #header-bar, :root.yotsuba #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.yotsuba #header-bar, :root.yotsuba #notifications {\n\ - color: #B86;\n\ -}\n\ -:root.yotsuba #board-list a, :root.yotsuba #shortcuts a {\n\ - color: #800000;\n\ -}\n\ -/* Settings */\n\ -:root.yotsuba #fourchanx-settings fieldset, :root.yotsuba .section-main div::before {\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.yotsuba .suboption-list > div:last-of-type {\n\ - background-color: #F0E0D6;\n\ -}\n\ -/* Catalog */\n\ -:root.yotsuba.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #F0E0D6;\n\ -}\n\ -:root.yotsuba.werkTyme .catalog-thread:not(:hover),\n\ -:root.yotsuba.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.yotsuba.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.yotsuba.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #D9BFB7;\n\ -}\n\ -/* Quote */\n\ -:root.yotsuba .backlink.deadlink {\n\ - color: #00E !important;\n\ -}\n\ -:root.yotsuba .inline {\n\ - border-color: #D9BFB7;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.yotsuba .indicator {\n\ - color: #F0E0D6;\n\ -}\n\ -/* QR */\n\ -.yotsuba #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.yotsuba .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.yotsuba .qr-link {\n\ - border-color: rgb(225, 209, 199) rgb(225, 209, 199) rgb(210, 194, 184);\n\ - background: linear-gradient(#FFEFE5, #F0E0D6) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.yotsuba .qr-link:hover {\n\ - background: #F0E0D6;\n\ -}\n\ -/* Menu */\n\ -:root.yotsuba #menu {\n\ - color: #800000;\n\ -}\n\ -:root.yotsuba .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.yotsuba .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.yotsuba .unread-mark-read {\n\ - background-color: rgba(240,224,214,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.yotsuba .replies-quoting-you > a, :root.yotsuba #watcher-link.replies-quoting-you, :root.yotsuba .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.yotsuba .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.yotsuba-b .dialog {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.yotsuba-b .field:focus,\n\ -:root.yotsuba-b .field.focus {\n\ - border-color: #98E;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.yotsuba-b.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8) !important;\n\ -}\n\ -:root.yotsuba-b.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.yotsuba-b #header-bar.dialog {\n\ - background-color: rgba(214,218,240,0.98);\n\ -}\n\ -:root.yotsuba-b:not(.fixed) #header-bar, :root.yotsuba-b #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\n\ - color: #89A;\n\ -}\n\ -:root.yotsuba-b #board-list a, :root.yotsuba-b #shortcuts a {\n\ - color: #34345C;\n\ -}\n\ -/* Settings */\n\ -:root.yotsuba-b #fourchanx-settings fieldset, :root.yotsuba-b .section-main div::before {\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.yotsuba-b .suboption-list > div:last-of-type {\n\ - background-color: #D6DAF0;\n\ -}\n\ -/* Catalog */\n\ -:root.yotsuba-b.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #D6DAF0;\n\ -}\n\ -:root.yotsuba-b.werkTyme .catalog-thread:not(:hover),\n\ -:root.yotsuba-b.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.yotsuba-b.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.yotsuba-b.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #B7C5D9;\n\ -}\n\ -/* Quote */\n\ -:root.yotsuba-b .backlink.deadlink {\n\ - color: #34345C !important;\n\ -}\n\ -:root.yotsuba-b .inline {\n\ - border-color: #B7C5D9;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.yotsuba-b .indicator {\n\ - color: #D6DAF0;\n\ -}\n\ -/* QR */\n\ -.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.yotsuba-b .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.yotsuba-b .qr-link {\n\ - border-color: rgb(199, 203, 225) rgb(199, 203, 225) rgb(184, 188, 210);\n\ - background: linear-gradient(#E5E9FF, #D6DAF0) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.yotsuba-b .qr-link:hover {\n\ - background: #D9DDF3;\n\ -}\n\ -/* Menu */\n\ -:root.yotsuba-b #menu {\n\ - color: #000;\n\ -}\n\ -:root.yotsuba-b .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.yotsuba-b .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.yotsuba-b .unread-mark-read {\n\ - background-color: rgba(214,218,240,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.yotsuba-b .replies-quoting-you > a, :root.yotsuba-b #watcher-link.replies-quoting-you {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.yotsuba-b .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.futaba .dialog {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.futaba .field:focus,\n\ -:root.futaba .field.focus {\n\ - border-color: #EA8;\n\ -}\n\ -/* Header */\n\ -:root.futaba #header-bar.dialog {\n\ - background-color: rgba(240,224,214,0.98);\n\ -}\n\ -:root.futaba:not(.fixed) #header-bar, :root.futaba #notifications {\n\ - font-size: 11pt;\n\ -}\n\ -:root.futaba #header-bar, :root.futaba #notifications {\n\ - color: #B86;\n\ -}\n\ -:root.futaba #header-bar a, :root.futaba #notifications a {\n\ - color: #800000;\n\ -}\n\ -/* Settings */\n\ -:root.futaba #fourchanx-settings fieldset, :root.futaba .section-main div::before {\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.futaba .suboption-list > div:last-of-type {\n\ - background-color: #F0E0D6;\n\ -}\n\ -/* Catalog */\n\ -:root.futaba.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #F0E0D6;\n\ -}\n\ -:root.futaba.werkTyme .catalog-thread:not(:hover),\n\ -:root.futaba.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.futaba.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.futaba.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #D9BFB7;\n\ -}\n\ -/* Quote */\n\ -:root.futaba .backlink.deadlink {\n\ - color: #00E !important;\n\ -}\n\ -:root.futaba .inline {\n\ - border-color: #D9BFB7;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.futaba .indicator {\n\ - color: #F0E0D6;\n\ -}\n\ -/* Anonymize */\n\ -:root.futaba.anonymize $site$info$name::before {\n\ - font-size: 12pt;\n\ -}\n\ -/* QR */\n\ -.futaba #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #F0E0D6;\n\ - border-color: #D9BFB7;\n\ -}\n\ -:root.futaba .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.futaba .qr-link {\n\ - border-color: rgb(225, 209, 199) rgb(225, 209, 199) rgb(210, 194, 184);\n\ - background: linear-gradient(#FFEFE5, #F0E0D6) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.futaba .qr-link:hover {\n\ - background: #F0E0D6;\n\ -}\n\ -/* Menu */\n\ -:root.futaba #menu {\n\ - color: #800000;\n\ -}\n\ -:root.futaba .entry {\n\ - font-size: 12pt;\n\ -}\n\ -:root.futaba .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.futaba .unread-mark-read {\n\ - background-color: rgba(240,224,214,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.futaba .replies-quoting-you > a, :root.futaba #watcher-link.replies-quoting-you, :root.futaba .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.futaba .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.burichan .dialog {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.burichan .field:focus,\n\ -:root.burichan .field.focus {\n\ - border-color: #98E;\n\ -}\n\ -/* Header */\n\ -:root.burichan #header-bar.dialog {\n\ - background-color: rgba(214,218,240,0.98);\n\ -}\n\ -:root.burichan:not(.fixed) #header-bar, :root.burichan #header-bar #notifications {\n\ - font-size: 11pt;\n\ -}\n\ -:root.burichan #header-bar, :root.burichan #header-bar #notifications {\n\ - color: #89A;\n\ -}\n\ -:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\n\ - color: #34345C;\n\ -}\n\ -/* Settings */\n\ -:root.burichan #fourchanx-settings fieldset, :root.burichan .section-main div::before {\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.burichan .suboption-list > div:last-of-type {\n\ - background-color: #D6DAF0;\n\ -}\n\ -/* Catalog */\n\ -:root.burichan.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #D6DAF0;\n\ -}\n\ -:root.burichan.werkTyme .catalog-thread:not(:hover),\n\ -:root.burichan.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.burichan.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.burichan.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #B7C5D9;\n\ -}\n\ -/* Quote */\n\ -:root.burichan .backlink.deadlink {\n\ - color: #34345C !important;\n\ -}\n\ -:root.burichan .inline {\n\ - border-color: #B7C5D9;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.burichan .indicator {\n\ - color: #D6DAF0;\n\ -}\n\ -/* Anonymize */\n\ -:root.burichan.anonymize $site$info$name::before {\n\ - font-size: 12pt;\n\ -}\n\ -/* QR */\n\ -.burichan #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #D6DAF0;\n\ - border-color: #B7C5D9;\n\ -}\n\ -:root.burichan .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.burichan .qr-link {\n\ - border-color: rgb(199, 203, 225) rgb(199, 203, 225) rgb(184, 188, 210);\n\ - background: linear-gradient(#E5E9FF, #D6DAF0) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.burichan .qr-link:hover {\n\ - background: #D9DDF3;\n\ -}\n\ -/* Menu */\n\ -:root.burichan #menu {\n\ - color: #000000;\n\ -}\n\ -:root.burichan .entry {\n\ - font-size: 12pt;\n\ -}\n\ -:root.burichan .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.burichan .unread-mark-read {\n\ - background-color: rgba(214,218,240,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.burichan .replies-quoting-you > a, :root.burichan #watcher-link.replies-quoting-you, :root.burichan .last-page > a > .watcher-page {\n\ - color: #F00;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.burichan .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.tomorrow .dialog {\n\ - background-color: #282A2E;\n\ - border-color: #111;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.tomorrow #arc-list span.quote {\n\ - color: #B5BD68;\n\ -}\n\ -:root.tomorrow.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8) !important;\n\ -}\n\ -:root.tomorrow.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.tomorrow #header-bar.dialog {\n\ - background-color: rgba(40,42,46,0.9);\n\ -}\n\ -:root.tomorrow:not(.fixed) #header-bar, :root.tomorrow #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.tomorrow #header-bar, :root.tomorrow #notifications {\n\ - color: #C5C8C6;\n\ -}\n\ -:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\n\ - color: #81A2BE;\n\ -}\n\ -:root.tomorrow.shortcut-icons .native-settings {\n\ - background-image: url('//s.4cdn.org/image/favicon-ws.ico');\n\ -}\n\ -/* Settings */\n\ -:root.tomorrow #fourchanx-settings fieldset, :root.tomorrow .section-main div::before {\n\ - border-color: #111;\n\ -}\n\ -:root.tomorrow .suboption-list > div:last-of-type {\n\ - background-color: #282A2E;\n\ -}\n\ -/* Catalog */\n\ -:root.tomorrow.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #282A2E;\n\ -}\n\ -:root.tomorrow.werkTyme .catalog-thread:not(:hover),\n\ -:root.tomorrow.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.tomorrow.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.tomorrow.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #111;\n\ -}\n\ -/* Quote */\n\ -:root.tomorrow .backlink.deadlink {\n\ - color: #81A2BE !important;\n\ -}\n\ -:root.tomorrow .inline {\n\ - border-color: #111;\n\ - background-color: rgba(0, 0, 0, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.tomorrow .indicator {\n\ - color: #282A2E;\n\ -}\n\ -/* Highlighting */\n\ -:root.tomorrow .qphl {\n\ - outline: 2px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.tomorrow.highlight-you .quotesYou$site$highlightable$op,\n\ -:root.tomorrow.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.tomorrow.highlight-own .yourPost$site$highlightable$op,\n\ -:root.tomorrow.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8);\n\ -}\n\ -:root.tomorrow .filter-highlight$site$highlightable$op,\n\ -:root.tomorrow .filter-highlight$site$highlightable$reply {\n\ - box-shadow: inset 5px 0 rgba(145, 182, 214, .5);\n\ -}\n\ -:root.tomorrow.highlight-own .yourPost > $site$sideArrows,\n\ -:root.tomorrow.highlight-you .quotesYou > $site$sideArrows,\n\ -:root.tomorrow .filter-highlight > $site$sideArrows {\n\ - color: rgb(155, 185, 210);\n\ -}\n\ -:root.tomorrow .catalog-thread.filter-highlight .catalog-thumb,\n\ -:root.tomorrow.werkTyme .catalog-thread.filter-highlight:not(:hover),\n\ -:root.tomorrow.werkTyme:not(.catalog-hover-expand) .catalog-thread.filter-highlight,\n\ -:root.tomorrow.werkTyme.catalog-hover-expand .catalog-thread.filter-highlight > .catalog-container:hover > .catalog-post {\n\ - box-shadow: 0 0 3px 3px rgba(64, 192, 255, .7);\n\ -}\n\ -:root.tomorrow .catalog-thread.watched .catalog-thumb,\n\ -:root.tomorrow.werkTyme .catalog-thread.watched:not(:hover),\n\ -:root.tomorrow.werkTyme:not(.catalog-hover-expand) .catalog-thread.watched,\n\ -:root.tomorrow.werkTyme.catalog-hover-expand .catalog-thread.watched > .catalog-container:hover > .catalog-post {\n\ - border: 2px solid rgb(64, 192, 255);\n\ -}\n\ -/* QR */\n\ -.tomorrow #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #282A2E;\n\ - border-color: #111;\n\ -}\n\ -:root.tomorrow .qr-preview {\n\ - background-color: rgba(255, 255, 255, .15);\n\ -}\n\ -:root.tomorrow #qr .field {\n\ - background-color: rgb(26, 27, 29);\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.tomorrow #qr .field:focus,\n\ -:root.tomorrow #qr .field.focus {\n\ - border-color: rgb(129, 162, 190) !important;\n\ - background-color: rgb(30,32,36);\n\ -}\n\ -:root.tomorrow .persona button {\n\ - background: linear-gradient(to bottom, #2E3035, #222427) no-repeat;\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ - outline: none;\n\ -}\n\ -:root.tomorrow .persona button::-moz-focus-inner {\n\ - border: none;\n\ -}\n\ -:root.tomorrow .persona button:focus {\n\ - border-color: rgb(129, 162, 190);\n\ -}\n\ -:root.tomorrow #qr.sjis-preview #sjis-toggle,\n\ -:root.tomorrow #qr.tex-preview #tex-preview-button {\n\ - background: rgb(26, 27, 29);\n\ -}\n\ -:root.tomorrow #qr select,\n\ -:root.tomorrow #file-n-submit > input,\n\ -:root.tomorrow #qr-draw-button {\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.tomorrow #qr-filename {\n\ - color: rgb(197,200,198);\n\ -}\n\ -:root.tomorrow .qr-link {\n\ - border-color: rgb(25, 27, 31) rgb(25, 27, 31) rgb(10, 12, 16);\n\ - background: linear-gradient(#37393D, #282A2E) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.tomorrow .qr-link:hover {\n\ - background: #282A2E;\n\ -}\n\ -/* Menu */\n\ -:root.tomorrow #menu {\n\ - color: #C5C8C6;\n\ -}\n\ -:root.tomorrow .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.tomorrow .focused.entry {\n\ - background: rgba(0, 0, 0, .33);\n\ -}\n\ -/* Unread */\n\ -:root.tomorrow .unread-line {\n\ - border-color: rgb(197, 200, 198);\n\ -}\n\ -:root.tomorrow .unread-mark-read {\n\ - background-color: rgba(40,42,46,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.tomorrow .replies-quoting-you > a, :root.tomorrow #watcher-link.replies-quoting-you, :root.tomorrow .last-page > a > .watcher-page {\n\ - color: #F00 !important;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.tomorrow .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.photon .dialog {\n\ - background-color: #DDD;\n\ - border-color: #CCC;\n\ -}\n\ -:root.photon .field:focus,\n\ -:root.photon .field.focus {\n\ - border-color: #EA8;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.photon #arc-list tr:nth-of-type(odd) span.quote {\n\ - color: #C0E17A;\n\ -}\n\ -:root.photon.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(221, 0, 0, .8) !important;\n\ -}\n\ -:root.photon.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(221, 0, 0, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.photon #header-bar.dialog {\n\ - background-color: rgba(221,221,221,0.98);\n\ -}\n\ -:root.photon:not(.fixed) #header-bar, :root.photon #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.photon #header-bar, :root.photon #notifications {\n\ - color: #333;\n\ -}\n\ -:root.photon #header-bar a, :root.photon #notifications a {\n\ - color: #FF6600;\n\ -}\n\ -/* Settings */\n\ -:root.photon #fourchanx-settings fieldset, :root.photon .section-main div::before {\n\ - border-color: #CCC;\n\ -}\n\ -:root.photon .suboption-list > div:last-of-type {\n\ - background-color: #DDD;\n\ -}\n\ -/* Catalog */\n\ -:root.photon.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #DDD;\n\ -}\n\ -:root.photon.werkTyme .catalog-thread:not(:hover),\n\ -:root.photon.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.photon.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.photon.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #CCC;\n\ -}\n\ -/* Quote */\n\ -:root.photon .backlink.deadlink {\n\ - color: #F60 !important;\n\ -}\n\ -:root.photon .inline {\n\ - border-color: #CCC;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.photon .indicator {\n\ - color: #DDD;\n\ -}\n\ -/* QR */\n\ -.photon #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #DDD;\n\ - border-color: #CCC;\n\ -}\n\ -:root.photon .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.photon .qr-link {\n\ - border-color: rgb(206, 206, 206) rgb(206, 206, 206) rgb(191, 191, 191);\n\ - background: linear-gradient(#ECECEC, #DDD) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.photon .qr-link:hover {\n\ - background: #DDDDDD;\n\ -}\n\ -/* Menu */\n\ -:root.photon #menu {\n\ - color: #333;\n\ -}\n\ -:root.photon .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.photon .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.photon .unread-mark-read {\n\ - background-color: rgba(221,221,221,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.photon .replies-quoting-you > a, :root.photon #watcher-link.replies-quoting-you, :root.photon .last-page > a > .watcher-page {\n\ - color: #00F !important;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.photon .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* General */\n\ -:root.spooky .dialog {\n\ - background-color: #171526;\n\ - border-color: #707070;\n\ -}\n\ -:root.spooky .field:focus,\n\ -:root.spooky .field.focus {\n\ - border-color: #98E;\n\ -}\n\ -/* 4chan style fixes */\n\ -:root.spooky #arc-list span.quote {\n\ - color: #634C2C;\n\ -}\n\ -:root.spooky.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8) !important;\n\ -}\n\ -:root.spooky.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8) !important;\n\ -}\n\ -/* Header */\n\ -:root.spooky #header-bar.dialog {\n\ - background-color: rgba(23,21,38,0.98);\n\ -}\n\ -:root.spooky:not(.fixed) #header-bar, :root.spooky #notifications {\n\ - font-size: 9pt;\n\ -}\n\ -:root.spooky #header-bar, :root.spooky #notifications {\n\ - color: #C49756;\n\ -}\n\ -:root.spooky #board-list a, :root.spooky #shortcuts a {\n\ - color: #FE9600;\n\ -}\n\ -:root.spooky.shortcut-icons .native-settings {\n\ - background-image: url('//s.4cdn.org/image/favicon-ws.ico');\n\ -}\n\ -/* Settings */\n\ -:root.spooky #fourchanx-settings fieldset, :root.spooky .section-main div::before {\n\ - border-color: #707070;\n\ -}\n\ -:root.spooky .suboption-list > div:last-of-type {\n\ - background-color: #171526;\n\ -}\n\ -/* Catalog */\n\ -:root.spooky.catalog-hover-expand .catalog-container:hover > .post {\n\ - background-color: #171526;\n\ -}\n\ -:root.spooky.werkTyme .catalog-thread:not(:hover),\n\ -:root.spooky.werkTyme:not(.catalog-hover-expand) .catalog-thread,\n\ -:root.spooky.catalog-hover-expand .catalog-container:hover > .post,\n\ -:root.spooky.catalog-hover-expand .catalog-container:hover .catalog-reply {\n\ - border-color: #707070;\n\ -}\n\ -/* Quote */\n\ -:root.spooky .backlink.deadlink {\n\ - color: #FE9600 !important;\n\ -}\n\ -:root.spooky .inline {\n\ - border-color: #707070;\n\ - background-color: rgba(255, 255, 255, .14);\n\ -}\n\ -/* Fappe and Werk Tyme */\n\ -:root.spooky .indicator {\n\ - color: #171526;\n\ -}\n\ -/* Highlighting */\n\ -:root.spooky .qphl {\n\ - outline: 2px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.spooky.highlight-you .quotesYou$site$highlightable$op,\n\ -:root.spooky.highlight-you .quotesYou$site$highlightable$reply {\n\ - border-left: 3px solid rgba(145, 182, 214, .8);\n\ -}\n\ -:root.spooky.highlight-own .yourPost$site$highlightable$op,\n\ -:root.spooky.highlight-own .yourPost$site$highlightable$reply {\n\ - border-left: 3px dashed rgba(145, 182, 214, .8);\n\ -}\n\ -:root.spooky .filter-highlight$site$highlightable$op,\n\ -:root.spooky .filter-highlight$site$highlightable$reply {\n\ - box-shadow: inset 5px 0 rgba(145, 182, 214, .5);\n\ -}\n\ -:root.spooky.highlight-own .yourPost > $site$sideArrows,\n\ -:root.spooky.highlight-you .quotesYou > $site$sideArrows,\n\ -:root.spooky .filter-highlight > $site$sideArrows {\n\ - color: rgb(155, 185, 210);\n\ -}\n\ -/* QR */\n\ -.spooky #dump-list::-webkit-scrollbar-thumb {\n\ - background-color: #171526;\n\ - border-color: #707070;\n\ -}\n\ -:root.spooky .qr-preview {\n\ - background-color: rgba(0, 0, 0, .15);\n\ -}\n\ -:root.spooky #qr .field {\n\ - background-color: rgb(26, 27, 29);\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.spooky #qr .field:focus,\n\ -:root.spooky #qr .field.focus {\n\ - border-color: rgb(254, 150, 0) !important;\n\ - background-color: rgb(30,32,36);\n\ -}\n\ -:root.spooky .persona button {\n\ - background: linear-gradient(to bottom, #2E3035, #222427) no-repeat;\n\ - color: rgb(197,200,198);\n\ - border-color: rgb(40, 41, 42);\n\ - outline: none;\n\ -}\n\ -:root.spooky .persona button::-moz-focus-inner {\n\ - border: none;\n\ -}\n\ -:root.spooky .persona button:focus {\n\ - border-color: rgb(254, 150, 0);\n\ -}\n\ -:root.spooky #qr.sjis-preview #sjis-toggle,\n\ -:root.spooky #qr.tex-preview #tex-preview-button {\n\ - background: rgb(26, 27, 29);\n\ -}\n\ -:root.spooky #qr select,\n\ -:root.spooky #file-n-submit > input,\n\ -:root.spooky #qr-draw-button {\n\ - border-color: rgb(40, 41, 42);\n\ -}\n\ -:root.spooky #qr-filename {\n\ - color: rgb(197,200,198);\n\ -}\n\ -:root.spooky .qr-link {\n\ - border-color: rgb(8, 6, 23) rgb(8, 6, 23) rgb(0, 0, 8);\n\ - background: linear-gradient(#262435, #171526) repeat scroll 0% 0% transparent;\n\ -}\n\ -:root.spooky .qr-link:hover {\n\ - background: #1A1829;\n\ -}\n\ -/* Menu */\n\ -:root.spooky #menu {\n\ - color: #FE9600;\n\ -}\n\ -:root.spooky .entry {\n\ - font-size: 10pt;\n\ -}\n\ -:root.spooky .focused.entry {\n\ - background: rgba(255, 255, 255, .33);\n\ -}\n\ -/* Unread */\n\ -:root.spooky .unread-line {\n\ - border-color: rgb(197, 200, 198);\n\ - visibility: visible;\n\ - opacity: 1;\n\ -}\n\ -:root.spooky .unread-mark-read {\n\ - background-color: rgba(23,21,38,0.5);\n\ -}\n\ -/* Thread Watcher */\n\ -:root.spooky .replies-quoting-you > a, :root.spooky #watcher-link.replies-quoting-you, :root.spooky .last-page > a > .watcher-page {\n\ - color: #F00 !important;\n\ -}\n\ -/* Watcher Favicon */\n\ -:root.spooky .watch-thread-link\n\ -{\n\ - background-image: url(\"data:image/svg+xml,\");\n\ -}\n\ -/* Link Title Favicons */\n\ -.linkify.audio::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.bitchute::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAadQTFRFAAAAwzw8xDs7cY6O0iws0ysrtF9f0Sws1CwsyzU1zTIy1igoyzQ01icnY7i4t0hI0S4u0ysr1Soq1ikp1ikp1Soq0ysr0S4uu0VFzjEx1Csr1ygo2Ccn2Ccn1ygo1CoqzjExzjAw1Skp2Ccn2Ccn1ikp0TAwxzY21Soq1SoqyzQ00iws1ygo1ygo0yws1Soq1Skp1igo1igo1igo1igo1igo1igo1Coq1Soq0C0t1ygo1ygo0S4unV5e1Csr1ygo1ygo1CsruUdHxzg41Skp1ygo1CsryTU10C4u1igo1ycn1ygo0i0txjo60S0t1ikp1ygo1ikp1Cws1Coq1Coq0yws0S0tyzQ00iws1Soq0ysr0i0txDs72Ccn2CUl2CYm2CQk3EFB2S8v2zw82jY24FZW3D0931FR3EBA3UND8LS04FVV7qys4V9f4WBg+erq766u9t7e7qqq2Ckp54KC9+Pj6pSU+Ojo5XNz9NHR6YqK8bu765ub5G5u9M3N6ImJ88vL5XV165eX3UVF6pWV3UhI2Soq2jU12Coq2jQ02Cgo2Sws////FaxLuAAAAF10Uk5TAAAAAAAAAAAAAAAAAAAAASJnoLy9oWolAhBz1vr72XgTGKf8/a4cCpuiDVvz9mS6xOvy9vzg6aGsPOToRAFv9fh2Awm07XgIMd765UEDOsfemVhhY00nBommbCkEI8horgAAAL5JREFUKBUFwbFKA0EUQNF7387sMq4EmzRpLSSdIBYKFv6Af2prnSYkRT4gWFgkCBJQ0EIFdcZzBCeqqh4qdk7VW2ChPusw02sAYKU7z7wEAAA2piQKFbrWSHazc1J0XWs5pdxPDykcVX+7Y9UxUsSo+s7PibqPFBRV/C5qi4i/UkrJrc7L47Bt4ZWnUaMCAE9GSrtKBQD2fR+bnAEAeOn7dUTOwApe35bDsPz0zsniQlV98IN0tJ3f6P0XAMA/kxou7OXCdnoAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.clyp::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAwUExURTSY22ey5E2l4KbS75rM7Y3F64C/6f///8zl9nS45r/f9PL5/UGe3bPY8Vqr4v///wNjrzUAAAABYktHRA8YugDZAAAAB3RJTUUH4AINEi85AIH95AAAAE9JREFUCNdjYMAGGBWgDGYHCM2a3hkAZmi0dzSBaKaO9o5moCqmLiCjYzNQyw4QowIodQzI6E0AKcpo72gE6+Jyb1kAMehUA9RktgdYbQYAjGIVNGGXBJkAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.dailymotion::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQBk3ff6/trp+kKO5wZt3xx54q7P9Ozz/IS17zOG5WKh653E8sbc9/GbbcoAAABZSURBVAjXY2BAASyhDhAGc9oECMOjyAAiESEEYrBYpLWBGcwHxcvBjDDxHelghpF0yDQwY3kVgweEUeEQDWbMEepqAjO8FMsLIeYsU8o+BrbCdWboTAe4AwALXxWGjW41FwAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.gfycat::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAjVBMVEWn3gCo3gSr3w2t4BSu4Bav4Ri35C+45DK45DO55DXA50rA50vB50zC6E/D6FTF6VjG6VvL62vN7G/P7XbQ7XfW74vY8JDa8ZTe8qDe8qLf86Pi9Kzj9K7k9LHp9sDp98Lq98Ps+Mr0++L5/O75/fD6/fH6/fL6/fP7/fT7/fb8/ff8/vj8/vn+/v7///91X4cfAAAAcklEQVR42o3M2xKBUACF4aVQckrIuRJK6H//x2sme4/MuPDfre9i6c/Cc3U5Dj87BuAxsXvGu6JvIIXEHRWwNHCHQNrCzkAFkbSBg4EM8i+Yw7PXBa3zRfuxVyf/Bis7nKwGKAcWxgC8prI5Sc315OlnDfzpDar2S9/oAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.gist::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABblBMVEXc3NykpKTW1tbb29ugoKCdnZ0AAAACAgIEDRcKCgoMDAwODg4QIzYRDAoTExMUDwwVAg0WICsaEw8aGhoiCBklGxUmERwwKCQ7LSU7Ozs8LSZFLyNINi1JNyxJNy1KSklMOi5VR1FXV1daQTRkZGRseYZwU0F4eHh7dnR8bWV/YE6IdGiKcGCKkJaNgYeNjY2RdGOScWCUcWCZmZmhoaGkpKSoqKirfmaurq6xsbG1tbW6urq+vr7AbmzBb23CwsLGxsbHx8fHyMjJycnJysrMzMzOiYbPi4fQ0NDRoYbT09PU1NTW1tbY2NjZqIzZ2dnb29vd3d3f39/i4uLktZrk5OTl5eXm5ubn5+fo6Ojq6urs7OzttKLu7u7wuqbw8PDx8fHz8/P4+Pj5+fn7uZj8vpz9ya79ybD/tZf/upr/wZ//w6H/xKH/xaL/xrH/yqj/y7T/zqv/z7D/07D/17n/2Lv/2Lz/3L//38n/4Mk3Q/ZuAAAABnRSTlMSFcbGzc5MNKFvAAAA1klEQVQoz2NgYPZHAswMDEwRSclwkBTBxOARn4gE4j0YXBOiJNUDg7y8Ar1UlOITXBkcY73Z2Li42dg42dn4wmIdGeyjQ7nZoEA4PNqewSZKlw0O9KJsGKwjBdl4ZeWkJGQUhNjEIq0ZrMI5+D0ri7Jz8itCRAXCrRgsQ3mUy+xicrPSbfO0REItGSyCVaVL3ONSU9LcCtQUgy0YzIJ85M1LizMzCsv9xF2CzBhMAwN99TV1DI0MtDWcAgNNGUycA5CAswkDi5kDwrMOZiwMjKzGSICVEQDhZj0UQV7PewAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.image::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.installgentoo::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABcVBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3dIYAAAAAAAAAAAAbGh4BBAcCBgoBBgoCBwsCCQ/QzucCCA7MyuXZ1eUBBQmTh8fo5/i9svIAAADh3vQAAAACCA0CCQ8CCQ4DDBQbGCUDChDr6vgAAAAAAAAREBIDCxK6tdfe2fTv7/cDCxIDDBQEDRUHDhgMJjXk4PZdXWdLUFoUNEYOKDgSMUMRLUBneI4eTGj08/QmW3onW3rTzvfOx/giU3IiVHMkWHdEaYJobHv3+PokWHpua6TNy9xZgZ+1quz8/foQKj0XPFInWn0nW38tZ4o6fqg8gq48grA9hrU/i7pAhrNAiLdBjLtEjr1FksNIjr5Il8pImMtKWnNqhL97odKFqti5q/q5rPq60+nCt/vLw/vPx/jV0vHY0/rc1/rg2/vh3fzn4fzu6/vx8vf19Pv19Pz49/v5+Pv8/Pv8/fr9/vv+/frziVtUAAAAT3RSTlMABQYHCAoNDhARGRobL0ZOV1xdXV5fYGBmZnB0eX2MjZSaoaGio6mqqqustLq7zubo6Ojo6evt7u/x8fLy9/f4+Pj5+vr6+vr6+/39/v7+XKgUSwAAAMhJREFUKM9jYGDg4OZmZgABKINT1dBAhBHIYFMxMBIDisjbhoZbCTExsCu5hoeY8DEwcOkEx8fY6MqpucTGB0izglVEplcU5/gmRYWBVQDNMK+s0hN3SvMyBpsBNJxXw0NfwTEjVQZqHQMHj5RfWW5mliSEC7TPzK6yJD/bXZQRzGdXcisqLy309okA2Q4Eis4peQWmstqBCdGW/CABraC45ERBBs3A6Fh/AbAKTwsHa34QZW8NVsGuLqwswQSjQICTmYMFQaEDAAF8JHLfKGswAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.liveleak::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAlNJREFUGBkFwU2LVmUYAODrPu8Z5x1xSpRBXQyFoLsBE+wfiO5atJOgnf9DUPwFgtGinUgEaQsRhHYuMtpEiEWuG5iNjuOcj+c8z911xXcXL/68c3Dw1fzhg0QgEQAAEYGUKXFie9vxlSs/xk/rdavjGEkmkWSih65z4osv9GfOiK6LzEyZ2uGh4dUrmzs72ddlUUhkoiMr4PT167589Mh6c1N0nSRlqrX67dat+PDyZXRT19m5edPnt28rGFHxMcJ6d9fprS1/37tneP3aemPD1uamUydPOru3p5DdGOH0tWsu3LhhxIQJM2qEpRT/Pn3q/du3AhARSmvGTH0lplKMrVkiYpVpQaJlighzhDkzhmEA0fcWoqAfyaFW4zTlgCABxlrNmY4ylUzLsiREprFWc0T2M+ZSjKWY0AEaltZUjJixZJIpuk5pTWlNP2BYFvOyKJkCAKU1tTXHrZlqVWolUxdhxsfVSj9FmJfFMM9GdICGGa01HyMstYpMIFPJVNDPmYZSTOPoOEKHzNRlKpmWWh1j6TpLa2SKTKVWU6Z+Qolwdm/P9QcPZKa2LH69e9eIMs+WCL/cv2/98CGZPrt61am+V9APq1X89eyZ/968obVYaiXT4dGREgG+vnPHeHgYMsH2+fP+efEihtVKv7SWw/6+9/v7KYLMhIywTJPamvOXLomukyRsrNf+ePzYkpl9dJ3SWgSCSCQCfz5/7pMLF2yfO6eLiAQcHRz4/cmT+HR7O+Ob3d0fNt69+7a2BiICQCJbA0EgE5lpvbXl1OXL3/8Pfax4+6SjSukAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.pastebin::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAB1FBMVEUAAAAAAAAAAABWYWwAAABbY3BbYm5dZnFdZXJeZnMEBAQHCAhYYGpdZnFdZnBgaHIlJyomKCooKi09QkdESU5eZGtdYmhdYmleY2lrcXdqb3Rqb3Rqb3SSmJ+SlJeWmJutr7GtrrCWm6ChpKhbW1tmZmZvb290dHR3d3d4eHh5eXl6enp8fHx+gIJ/f3+CgoKDg4OEhISFhYWHh4eKioqKjI2Li4uMjIyOjo6Pj4+QkJCRkZGSkpKUlJSVl5mWlpaYmZqZm52ampqbm5ucnJydnZ2enp6fn5+hoaGioqKkpKSkpaalpaWmp6mmp6qnqauoqKioqquoqq2qqqqrrK2srKysra6srrCsrrGurq6vr6+wsLCxsbGysrKztLa0tLS1t7m2tra3t7e4uLi5ubm6urq7u7u8vLy9vb2+vr7AwMDAwsTBwcHExcfFxcXFxsnGxsbHx8fIyMjJycnMzMzNzc3Ozs7O0NLPz8/Q0NDR0dHR09XT09PV1dXV1dbV1tfV19rW1tbX19fX19jY2tzZ2dnZ2tva2tra3N3a3N7c3Nze3t7f39/f4OHg4ODi4uLl5+jm5ubs7Ozs7e3u7u7v7+/v8PDw8PDx8fHy8vLz8/P29vYSoLMZAAAAJHRSTlMABAUGCwsNHCAiLzMzMzZEYGJwgIuOnJycnqmqq9bc3+/w8fkZ0N/uAAAA/klEQVQoU2NgYGDl5YMDdgYGBmZZ3964CYFtIR3e9Q7K/AwMHI55KfaFmcHWMy3K3MwlGRg4wz0zdYpcorRbNbL0LaWAAp3ts2umV8wo6MupTauQBgqUG03VL7W3sfZSb1erAgm02M+yzYrVCXUy6zapAQlUx/dEdyX3J3ZHVUYVywAF8o2rDNN1Go2jzGLMokAC2QbuSc42mXmaOXop9iAtCXrJ5qXWjT59Abl2ESJAAX/tSIMMiyrrqQ3T6uS5gQK6kSqpqkUermGTexQFmYACflqR+hlWZSamzQpCLEDPsSmVVDT1TJw0JUhOAMRnYOARFRMTE5cQF+ZiBPIAII5B3EVG0b4AAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.peertube::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABIFBMVEUhHyAAAABzPBnxaA3CWBEnJSYbGRptbW16enpzc3PTayWhb04hHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyAhHyApIh+0UhMfHiBWMhvsZg7zaQ0hHyAhHyAXHCHzaQ3xaA3xaA3xaA3xaA0hHyAhHyDxaA3xaA3xaA3xaA3xaA3xaA0oJickIiMdGxwUEhPxaA3xaA3xaA1sbGxwcHB3d3eFhYXxaA3xaA3xaA1zc3Nzc3Nzc3Nzc3Nzc3PxaA3xaA3xaA1zc3Nzc3NtdHjxaA3xaA1yc3STcFnvaA/yaAxzc3N4c2/FbDFzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3MhHyDxaA1zc3MAAAAfljyVAAAAXHRSTlMAAAAAAAAAAAAAAAAZkjMBHOLXYArj8p0u2VsJ1XaGL/OhKyXc1WEN2gwk2/SjKgEYiS4B/tYFGosqAdleAxzj12ML9Z8s850rJWbYeYMs1F8Koiri1V0MGZY0AYbIBFIAAAABYktHRAH/Ai3eAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4wYXFBUVX81QWQAAAKxJREFUGNNVz9UWgkAQANDBtdbu7lZsxe7ubpH//wxBPKDzNvdMAmi0Oj0QQgAYjCazBX7BStvsDqHoAzTtdLklf+Dx+vwICRAIhsKRaCyOvpAwJ6Up8pXOZHOIAFm+UCzJEQuvMhWrIFBUa/WGkodmq40Ad7q9/kDFwnA05lpYYCbT2ZykFvxQDhhmuVpvcvxaHra7vfp72KflcMSYEOB0vlyx+By+3R9PMSfe+P0enM1454kAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTktMDYtMjRUMDM6MjE6MjEtMDc6MDDse6MAAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE5LTA2LTI0VDAzOjIxOjIxLTA3OjAwnSYbvAAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.soundcloud::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.streamable::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAABXFBMVEUPkPoNj/qExv0PkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoNj/oPkPoNj/oNj/qExv0PkPpruvwPkPornfoVk/opnPpnufwPkPqExv0Nj/oPkPoNj/oPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoPkPoOj/opnPsVk/oMjvoOkPoTkfo6pPsblfo3ovva7v7////v9/5Sr/whmPry+f5htvze8P7W7P5itvyl1v0imPu84P3o9P50v/zN6P73+/8lmvs8pfs+pfsKjvr9/v9EqfsNj/oom/v8/v9nufxAp/tJq/sQkPrb7v6t2f0IjPoclvr6/f9luPwUkvrp9f7h8f5ruvy/4f4kmftpuvwxoPum1v32+/8jmfpMrPvu9/7z+f9UsPs7pPv8/f/4/P9oufwalfpDqPsMj/ounvtVsPsnm/qzfQQ9AAAALXRSTlMAAAAggMzw0IYkBPb4iAamsgZ+jPwogpDO1vTYlPoulL4KivyUCiqO1PL01i67tUAWAAAAAWJLR0Q4oAel1gAAAAd0SU1FB+MGFxMuDXVcMbIAAADdSURBVBjTY2AAAmYWVjY2dg5OBgZGJiCXi4VbFwx4ePlAAlz8unAgIAgUENJFAsJMDMw8unp6+gaGRsYmpoa6IqIMYrp6ZuYWllbW5hY2toZ64gwSurp29g6OTs4urm7uHrqSDGy6nhZeet5WPr5+/gGBelJAgSCLYL+Q0LBw3YjIKKAAu250TGxcvE1CYlJySqquNAOHrl9aukVGZla2RU6uoZ4MA6esrl9evnWBYWFRMdBaOQYGXmSHyQNdyieA4CsogjzHpyQL4SqrqIJ9y8Cgpq6hqaWtogPyPgDmvSxRxBWM9AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOS0wNi0yNFQwMjo0NjoxMy0wNzowMCKUvXUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMDYtMjRUMDI6NDY6MTMtMDc6MDBTyQXJAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.twitchtv::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAYUExURf///2RBpWRBpWRBpWRBpWRBpWRBpf///+zQyUYAAAAGdFJOUwFdZX0lTzs4r5oAAAABYktHRAcWYYjrAAAAB3RJTUUH4AINEi42iSXRNAAAAD1JREFUCNdjYEiDAAZGGIMtjQEEUBlMCWoEGci6mGEMsxQgIy0BiB3AjLS0FAYQIw0kwABipoI1AhkBQBIAFCIXxiHgq80AAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.twitter::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAEsUExURf///1Cf21Gg3FGi31Gh3VKj4FGh3lKj4VKk4lKl41Ol5FOn51Sp6VSo6FOn5lCf21Gg3FGh3VGi31Gi31Gh3lGg3FGg3FGg3FGg3FGh3lGg3FGi31Kk4lKj4FGh3lGi31Kk4lGh3lGg3FGh3lOm5FOm5VGi31Kj4VSo6FGi31Gh3VGg3FKj4FOn51Gi31So6FWr7VOl5FGi31On51Sq6lKk4lOo51Sp6VOm5FSq61Ws7VOn51Oo51Sq61Ol5FOm5FSq61Wr7VOo51On51Sr7FWs7VSp6lGg3FGh3VOm5FWr7VSp6lKj4VOm5FSo6FSr7FWs7VWs7VWr7VSq6lOo51Om5FOo51So6FOm5VOl5FSq61Ws7VSr7FSp6lSp6VWs7lWr7VKk4lSq6v///6E3MNsAAABVdFJOUwAAAAAAAAAAAAAAAAAAAB0Ii+3xnBVTJhfsMKb+qTEp9GwBF/7lLAbo0m4pLkUTdvk2Ev3+EZnOBo/3Z8ffCRzH/D0OqPxiLnvx3UI8m9n1++GwXQZNS29BAAAAAWJLR0QAiAUdSAAAAAd0SU1FB+ACDRIwBwy67tEAAADKSURBVBjTY2BAB4xogIGRH8IQEBQSFhEVE2eQkJQC8ZmkQ8PCI2Rk5RjkIxUUlRgZlVWioqNjYlXVGNQ14iI1tbR14qLj4+MTdJkZ9PQNosJCE0OjgPz4KEMWBiPjhPiEmKQokIJ4E1MmBmazhHg4MGdlYmCzsLSC8ROsmRkZmFht4Eps7ViADmOzd4DyHZ2YmYACTOzOLmATXd04mIBOd/eQ9owFCXh5c7KB/MLi4+vnHxAYFBzCwcYEEmBi5uLm4eHl42RmAnsSAMZBLgZiFUQ5AAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.video::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAxgDGAP8nNqN7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gMZBjQQLEEqGwAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA5SURBVDjLY2AYaMDIwMDwn1JD/lPCZhpwL+B1wf///ykzgBhDiAoDfIYQZQAjIyP5BuDTPJqQqAQAvW0ZAMk8+EEAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vidlii::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACvlBMVEUCWv8HXf8AWv8AAAD///8AVP+bqP8AWv8AVO4AOqUAGkgAyf8APa0AL4QABAsASdEAVv8AUv8AUv8AVP8AWP8BWv8JXv8RYv8QYv8DW/8DXP8xdv9RiP9Af/8IXf8AKP8KXv8JXf8NYf8aaf8ATP0UZP0AVf8AT/8AT/8AVv8ATedvnPVAf/8AT/sYZvl0o/8PYf8udf8aa/8FXf8AVf8AOrRBe/Nvn/8AUv0aaPkXZ/8ATv8AKYQZYuwIXf8ca/wTZP8ASP8AED0HUNwZaf8xdPwDWv8AAAAAQMRcjvQAU/8AMZssb/Jmmf8AU/8AJXsRW+dSif8AUv8AAAAASdQtdP8ATv8AQ/8AQv8APbtKgfQud/8XZ/8TZP8FXP8AKIIcZO4wdP8AF08KU95tnv4gafhZi/Rnl/ZzofcocP8AAAAAQ8Q4efRwnvVmlvVcjvgrcfsAQsQAOK0APrwAQcUEStMLXPgDWv8AHE8APLEARdIAQ80ASeEAVf8AOJkAAAAAAAAAAAAABBMAJJIAY/9rmP+vxv90n/+buPv29/7C1P+zx/n///2Crv/7+fjs8f++z/f///3l6fX9/f/L2fj9/P5ilv9Nh/3h6f6vyf/D0vT///2lwP/Z5Pf3+P9OiP9klvr9/Puzyf+QsPX//fnW4v/k6vfv8/86ev94pfj///uRtf/y8vby9f9Fgv9EgPzt7/jj7f8mcf+eufj///x1pP/Z4fT///52pf9Uivv09fnV4v8ncf64yvj7+/6vxPX///yyyf9ynvr6+vvG1/8ocv3O2/fz9v53ofX8+/nb5v+YuPz//vy0yv8vdP3e5/fn7v/p7PX09//b5P7///6eu/9Df/zq7vjc5//I1vT//v3+/v////9+q/9Tivnn6fPy8/rW4fzI1/2qwv6YtPT8+fX39/jz9PqJrveTsvqfpuxrAAAAhXRSTlMAAAAAAAAAAAAAAAAAAAAABSlERA45nrSzP3TZ7e12Ao2LusMcrJYhFwaR/uhCwP/x5tZzBWHy+n3OvA8u17jmpwgPrOz5jAF2+3FA7PdYG8fuPQaX5jAGAV/39MCmdy/e/RGz/vj5/f/rAXj4//z13n52i5qmmFQ1lqOQaTgIBAYKEAYAKGjtAgAAAKNJREFUGBkFwT0uRGEYBtD3ZJ77uT8iGrXCAixCr7OCyRA2oCKqiUYkOgoJwhqUbMAKLEChVYhk4pxswvcWfFGVEbYtuJutqir9Ibc0uh0+V+mf5gY69yN2PzKJiTjCg8qa3uLRAJpKM9AMoL1VOi9zJ4CQ9z0jwHX+RAwAURUxAMSB/L7u35wCGlKaHrDkPGVmwhlc6FN6l1iHKxupn+djAPgHrEwa+qrzy0oAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vimeo::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAAIdZUKh6sLlLkLmr4LmsAMp88NrdYVW3MZj7Acstkrt9s1e5E7vN5EfI9JvdtKwuBijp5kpbl30eiDt8aG1uqRr7qTyNehxM+k4PCy3enB3OTg6Ovv9PXw+fz////L9U5WAAAAAXRSTlMAQObYZgAAAIFJREFUeNplz90OwiAMBWAQpAoyxclkP3je/y0H2AQXz0WT8100rRD6kNI9/cRroemQL3hXhoujZYj4OHoAmBvYGcBISwbWBvfXCrytnIDUQMkbsBpagMA7zhtQdyTFQAmIG7IkYniiZuh3XGsPqoOZkMOJOpAcLqUzNFGGu/57fwc1hgtp0mVSyQAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vine::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAHCUExURQAAAAC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+jwC+j////54tRLAAAACUdFJOUwAAAEK+9/e+QQIDAwEqzskfUZmUNHz2mrT++V1w+f5tCanNFUDwfEjtjAyyvg027Hki27QMBJzaHE/1+FkNsN0iZvv6bxyAlB589lQeyud0KB8PQO+ZBUrc+eXgcRG/3CoATe316Wxw/P6BAgBt+fp4IAwh0d4zM9q7Fm76qi605EMSrvfX/PRtAivF9IAJNMLxhA2KYlJ9AAAAAWJLR0SVCGB6gwAAAAd0SU1FB+ACDRI2MOJd7FgAAADrSURBVBjTLY9VWwJgGEPfiYWBha2YYHcHditgd3d3odjdivvBfgK727nYsyPiCrw03j6+fv6AaAMCgyAI1lElJBQSFh6hBxDJqOiY2Lh4SEKiIQlITmFqWrqRJkhGJrOA7Bzm5uUXsBBSVMySUpSVs6KyqrqmFmKuY30D0NjU3NLa1t6h9jvZ1Q30WGi19fb1KzAwyKFhYGSUY+MTkwpMTXNmFpibX+Di0rICWFldW9/A5tb2zu7ePtTrg0MeHePklPYzuDRw7uDF5RWvbwC32O0d7x8en55f4DHF6xv5/vHp6f/k6/vH+evuf1LAObptvSvrAAAAAElFTkSuQmCC') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.vocaroo::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -.linkify.youtube::before {\n\ - content: \"\";\n\ - background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\n\ - padding-left: 18px;\n\ -}\n\ -/* XXX Moved to end of stylesheet to avoid breaking whole stylesheet in Maxthon. */\n\ -@supports (text-decoration-style: dashed) or (-moz-text-decoration-style: dashed) {\n\ - .quotelink.forwardlink,\n\ - .backlink.forwardlink {\n\ - text-decoration: underline;\n\ - -moz-text-decoration-style: dashed;\n\ - text-decoration-style: dashed;\n\ - border-bottom: none;\n\ - }\n\ -}\n", - -report: -"#g-recaptcha,\n\ -:root:not(.js-enabled) #captchaContainerAlt {\n\ - height: auto;\n\ -}\n\ -#captchaContainerAlt td:nth-child(2) {\n\ - display: table-cell !important;\n\ -}\n\ -/* Archive reports */\n\ -#archive-report {\n\ - padding: 3px;\n\ -}\n\ -#archive-report-enabled {\n\ - vertical-align: middle;\n\ -}\n\ -#archive-report > label {\n\ - display: block;\n\ -}\n\ -#archive-report-reason {\n\ - display: block;\n\ - width: 98%;\n\ -}\n\ -.archive-report-success {\n\ - color: green;\n\ -}\n\ -.archive-report-error {\n\ - color: red;\n\ -}", - -www: -"#captcha-cnt {\n\ - height: auto;\n\ -}\n\ -:root:not(.js-enabled) #form {\n\ - display: block;\n\ -}\n\ -#bd > div[style], #bd > div[style] > * {\n\ - height: auto !important;\n\ - margin: 0 !important;\n\ - font-size: 0;\n\ -}\n", - -sub: function(css) { - var variables = { - site: g.SITE.selectors - }; - return css.replace(/\$[\w\$]+/g, function(name) { - var words = name.slice(1).split('$'); - var sel = variables; - for (var i = 0; i < words.length; i++) { - if (typeof sel !== 'object') return ':not(*)'; - sel = $.getOwn(sel, words[i]); - } - if (typeof sel !== 'string') return ':not(*)'; - return sel; - }); -} - -}; - -$ = (function() { - var $, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - $ = function(selector, root) { - if (root == null) { - root = d.body; - } - return root.querySelector(selector); - }; - - $.DAY = 24 * ($.HOUR = 60 * ($.MINUTE = 60 * ($.SECOND = 1000))); - - $.id = function(id) { - return d.getElementById(id); - }; - - $.ready = function(fc) { - var cb; - if (d.readyState !== 'loading') { - $.queueTask(fc); - return; - } - cb = function() { - $.off(d, 'DOMContentLoaded', cb); - return fc(); - }; - return $.on(d, 'DOMContentLoaded', cb); - }; - - $.formData = function(form) { - var fd, key, val; - if (form instanceof HTMLFormElement) { - return new FormData(form); - } - fd = new FormData(); - for (key in form) { - val = form[key]; - if (val) { - if (typeof val === 'object' && 'newName' in val) { - fd.append(key, val, val.newName); - } else { - fd.append(key, val); - } - } - } - return fd; - }; - - $.extend = function(object, properties) { - var key, val; - for (key in properties) { - val = properties[key]; - object[key] = val; - } - }; - - $.dict = function() { - return Object.create(null); - }; - - $.dict.clone = function(obj) { - var arr, i, j, key, map, ref, val; - if (typeof obj !== 'object' || obj === null) { - return obj; - } else if (obj instanceof Array) { - arr = []; - for (i = j = 0, ref = obj.length; j < ref; i = j += 1) { - arr.push($.dict.clone(obj[i])); - } - return arr; - } else { - map = Object.create(null); - for (key in obj) { - val = obj[key]; - map[key] = $.dict.clone(val); - } - return map; - } - }; - - $.dict.json = function(str) { - return $.dict.clone(JSON.parse(str)); - }; - - $.hasOwn = function(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - }; - - $.getOwn = function(obj, key) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - return obj[key]; - } else { - return void 0; - } - }; - - $.ajax = (function() { - var pageXHR; - if (window.wrappedJSObject && !XMLHttpRequest.wrappedJSObject) { - pageXHR = XPCNativeWrapper(window.wrappedJSObject.XMLHttpRequest); - } else { - pageXHR = XMLHttpRequest; - } - return function(url, options) { - var err, form, headers, key, onloadend, onprogress, r, ref, responseType, timeout, type, value, withCredentials; - if (options == null) { - options = {}; - } - if (options.responseType == null) { - options.responseType = 'json'; - } - options.type || (options.type = options.form && 'post' || 'get'); - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?(?:4chan|4channel|4cdn)\.org)\/adv\//, '$1//adv/'); - onloadend = options.onloadend, timeout = options.timeout, responseType = options.responseType, withCredentials = options.withCredentials, type = options.type, onprogress = options.onprogress, form = options.form, headers = options.headers; - r = new pageXHR(); - try { - r.open(type, url, true); - ref = headers || {}; - for (key in ref) { - value = ref[key]; - r.setRequestHeader(key, value); - } - $.extend(r, { - onloadend: onloadend, - timeout: timeout, - responseType: responseType, - withCredentials: withCredentials - }); - $.extend(r.upload, { - onprogress: onprogress - }); - $.on(r, 'error', function() { - if (!r.status) { - return c.warn("4chan X failed to load: " + url); - } - }); - r.send(form); - } catch (error) { - err = error; - if (err.result !== 0x805e0006) { - throw err; - } - r.onloadend = onloadend; - $.queueTask($.event, 'error', null, r); - $.queueTask($.event, 'loadend', null, r); - } - return r; - }; - })(); - - $.lastModified = $.dict(); - - $.whenModified = function(url, bucket, cb, options) { - var ajax, headers, params, r, ref, t, timeout, url0; - if (options == null) { - options = {}; - } - timeout = options.timeout, ajax = options.ajax; - params = []; - if ($.engine === 'blink') { - params.push("s=" + bucket); - } - if (url.split('/')[2] === 'a.4cdn.org') { - params.push("t=" + (Date.now())); - } - url0 = url; - if (params.length) { - url += '?' + params.join('&'); - } - headers = $.dict(); - if ((t = (ref = $.lastModified[bucket]) != null ? ref[url0] : void 0) != null) { - headers['If-Modified-Since'] = t; - } - r = (ajax || $.ajax)(url, { - onloadend: function() { - var base; - ((base = $.lastModified)[bucket] || (base[bucket] = $.dict()))[url0] = this.getResponseHeader('Last-Modified'); - return cb.call(this); - }, - timeout: timeout, - headers: headers - }); - return r; - }; - - (function() { - var reqs; - reqs = $.dict(); - $.cache = function(url, cb, options) { - var ajax, onloadend, req; - if (options == null) { - options = {}; - } - ajax = options.ajax; - if ((req = reqs[url])) { - if (req.callbacks) { - req.callbacks.push(cb); - } else { - $.queueTask(function() { - return cb.call(req, { - isCached: true - }); - }); - } - return req; - } - onloadend = function() { - var fn1, j, len, ref; - if (!this.status) { - delete reqs[url]; - } - ref = this.callbacks; - fn1 = (function(_this) { - return function(cb) { - return $.queueTask(function() { - return cb.call(_this, { - isCached: false - }); - }); - }; - })(this); - for (j = 0, len = ref.length; j < len; j++) { - cb = ref[j]; - fn1(cb); - } - return delete this.callbacks; - }; - req = (ajax || $.ajax)(url, { - onloadend: onloadend - }); - req.callbacks = [cb]; - return reqs[url] = req; - }; - return $.cleanCache = function(testf) { - var url; - for (url in reqs) { - if (testf(url)) { - delete reqs[url]; - } - } - }; - })(); - - $.cb = { - checked: function() { - if ($.hasOwn(Conf, this.name)) { - $.set(this.name, this.checked); - return Conf[this.name] = this.checked; - } - }, - value: function() { - if ($.hasOwn(Conf, this.name)) { - $.set(this.name, this.value.trim()); - return Conf[this.name] = this.value; - } - } - }; - - $.asap = function(test, cb) { - if (test()) { - return cb(); - } else { - return setTimeout($.asap, 25, test, cb); - } - }; - - $.onExists = function(root, selector, cb) { - var el, observer; - if (el = $(selector, root)) { - return cb(el); - } - observer = new MutationObserver(function() { - if (el = $(selector, root)) { - observer.disconnect(); - return cb(el); - } - }); - return observer.observe(root, { - childList: true, - subtree: true - }); - }; - - $.addStyle = function(css, id, test) { - var style; - if (test == null) { - test = 'head'; - } - style = $.el('style', { - textContent: css - }); - if (id != null) { - style.id = id; - } - $.onExists(doc, test, function() { - return $.add(d.head, style); - }); - return style; - }; - - $.addCSP = function(policy) { - var head, meta; - meta = $.el('meta', { - httpEquiv: 'Content-Security-Policy', - content: policy - }); - if (d.head) { - $.add(d.head, meta); - return $.rm(meta); - } else { - head = $.add(doc || d, $.el('head')); - $.add(head, meta); - return $.rm(head); - } - }; - - $.x = function(path, root) { - root || (root = d.body); - return d.evaluate(path, root, null, 8, null).singleNodeValue; - }; - - $.X = function(path, root) { - root || (root = d.body); - return d.evaluate(path, root, null, 7, null); - }; - - $.addClass = function() { - var className, classNames, el, j, len; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (j = 0, len = classNames.length; j < len; j++) { - className = classNames[j]; - el.classList.add(className); - } - }; - - $.rmClass = function() { - var className, classNames, el, j, len; - el = arguments[0], classNames = 2 <= arguments.length ? slice.call(arguments, 1) : []; - for (j = 0, len = classNames.length; j < len; j++) { - className = classNames[j]; - el.classList.remove(className); - } - }; - - $.toggleClass = function(el, className) { - return el.classList.toggle(className); - }; - - $.hasClass = function(el, className) { - return indexOf.call(el.classList, className) >= 0; - }; - - $.rm = function(el) { - return el != null ? el.remove() : void 0; - }; - - $.rmAll = function(root) { - return root.textContent = null; - }; - - $.tn = function(s) { - return d.createTextNode(s); - }; - - $.frag = function() { - return d.createDocumentFragment(); - }; - - $.nodes = function(nodes) { - var frag, j, len, node; - if (!(nodes instanceof Array)) { - return nodes; - } - frag = $.frag(); - for (j = 0, len = nodes.length; j < len; j++) { - node = nodes[j]; - frag.appendChild(node); - } - return frag; - }; - - $.add = function(parent, el) { - return parent.appendChild($.nodes(el)); - }; - - $.prepend = function(parent, el) { - return parent.insertBefore($.nodes(el), 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, properties2) { - var el; - el = d.createElement(tag); - if (properties) { - $.extend(el, properties); - } - if (properties2) { - $.extend(el, properties2); - } - return el; - }; - - $.on = function(el, events, handler) { - var event, j, len, ref; - ref = events.split(' '); - for (j = 0, len = ref.length; j < len; j++) { - event = ref[j]; - el.addEventListener(event, handler, false); - } - }; - - $.off = function(el, events, handler) { - var event, j, len, ref; - ref = events.split(' '); - for (j = 0, len = ref.length; j < len; j++) { - event = ref[j]; - el.removeEventListener(event, handler, false); - } - }; - - $.one = function(el, events, handler) { - var cb; - cb = function(e) { - $.off(el, events, cb); - return handler.call(this, e); - }; - return $.on(el, events, cb); - }; - - $.event = function(event, detail, root) { - if (root == null) { - root = d; - } - if ((detail != null) && typeof cloneInto === 'function') { - detail = cloneInto(detail, d.defaultView); - } - return root.dispatchEvent(new CustomEvent(event, { - bubbles: true, - cancelable: true, - detail: detail - })); - }; - - (function() { - var clone, err, ref, unsafeConstructors; - if (!(/PaleMoon\//.test(navigator.userAgent) && +(typeof GM_info !== "undefined" && GM_info !== null ? (ref = GM_info.version) != null ? ref.split('.')[0] : void 0 : void 0) >= 2 && typeof cloneInto === 'undefined')) { - return; - } - try { - return new CustomEvent('x', { - detail: {} - }); - } catch (error) { - err = error; - unsafeConstructors = { - Object: unsafeWindow.Object, - Array: unsafeWindow.Array - }; - clone = function(obj) { - var constructor, key, obj2, val; - if ((obj != null) && typeof obj === 'object' && (constructor = unsafeConstructors[obj.constructor.name])) { - obj2 = new constructor(); - for (key in obj) { - val = obj[key]; - obj2[key] = clone(val); - } - return obj2; - } else { - return obj; - } - }; - return $.event = function(event, detail, root) { - if (root == null) { - root = d; - } - return root.dispatchEvent(new CustomEvent(event, { - bubbles: true, - cancelable: true, - detail: clone(detail) - })); - }; - } - })(); - - $.modifiedClick = function(e) { - return e.shiftKey || e.altKey || e.ctrlKey || e.metaKey || e.button !== 0; - }; - - $.open = (typeof GM !== "undefined" && GM !== null ? GM.openInTab : void 0) != null ? GM.openInTab : typeof GM_openInTab !== "undefined" && GM_openInTab !== null ? GM_openInTab : function(url) { - return window.open(url, '_blank'); - }; - - $.debounce = function(wait, fn) { - var args, exec, lastCall, that, timeout; - lastCall = 0; - timeout = null; - that = null; - args = null; - exec = function() { - lastCall = Date.now(); - return fn.apply(that, args); - }; - return function() { - args = arguments; - that = this; - if (lastCall < Date.now() - wait) { - return exec(); - } - clearTimeout(timeout); - return timeout = setTimeout(exec, wait); - }; - }; - - $.queueTask = (function() { - var execTask, taskChannel, taskQueue; - taskQueue = []; - execTask = function() { - var args, func, task; - task = taskQueue.shift(); - func = task[0]; - args = Array.prototype.slice.call(task, 1); - return func.apply(func, args); - }; - if (window.MessageChannel) { - taskChannel = new MessageChannel(); - taskChannel.port1.onmessage = execTask; - return function() { - taskQueue.push(arguments); - return taskChannel.port2.postMessage(null); - }; - } else { - return function() { - taskQueue.push(arguments); - return setTimeout(execTask, 0); - }; - } - })(); - - $.global = function(fn, data) { - var script; - if (doc) { - script = $.el('script', { - textContent: "(" + fn + ").call(document.currentScript.dataset);" - }); - if (data) { - $.extend(script.dataset, data); - } - $.add(d.head || doc, script); - $.rm(script); - return script.dataset; - } else { - try { - fn.call(data); - } catch (error) {} - return data; - } - }; - - $.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]; - }; - - $.minmax = function(value, min, max) { - return (value < min ? min : value > max ? max : value); - }; - - $.hasAudio = function(video) { - return video.mozHasAudio || !!video.webkitAudioDecodedByteCount; - }; - - $.luma = function(rgb) { - return rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114; - }; - - $.unescape = function(text) { - if (text == null) { - return text; - } - return text.replace(/<[^>]*>/g, '').replace(/&(amp|#039|quot|lt|gt|#44);/g, function(c) { - return { - '&': '&', - ''': "'", - '"': '"', - '<': '<', - '>': '>', - ',': ',' - }[c]; - }); - }; - - $.isImage = function(url) { - return /\.(jpe?g|jfif|png|gif|bmp|webp|avif|jxl)$/i.test(url); - }; - - $.isVideo = function(url) { - return /\.(webm|mp4|ogv)$/i.test(url); - }; - - $.engine = (function() { - if (/Edge\//.test(navigator.userAgent)) { - return 'edge'; - } - if (/Chrome\//.test(navigator.userAgent)) { - return 'blink'; - } - if (/WebKit\//.test(navigator.userAgent)) { - return 'webkit'; - } - if (/Gecko\/|Goanna/.test(navigator.userAgent)) { - return 'gecko'; - } - })(); - - $.platform = 'userscript'; - - $.hasStorage = (function() { - try { - if (localStorage.getItem(g.NAMESPACE + 'hasStorage') === 'true') { - return true; - } - localStorage.setItem(g.NAMESPACE + 'hasStorage', 'true'); - return localStorage.getItem(g.NAMESPACE + 'hasStorage') === 'true'; - } catch (error) { - return false; - } - })(); - - $.item = function(key, val) { - var item; - item = $.dict(); - item[key] = val; - return item; - }; - - $.oneItemSugar = function(fn) { - return function(key, val, cb) { - if (typeof key === 'string') { - return fn($.item(key, val), cb); - } else { - return fn(key, val); - } - }; - }; - - $.syncing = $.dict(); - - $.securityCheck = function(data) { - if (location.protocol !== 'https:') { - return delete data['Redirect to HTTPS']; - } - }; - - if (((typeof GM !== "undefined" && GM !== null ? GM.deleteValue : void 0) != null) && window.BroadcastChannel && (typeof GM_addValueChangeListener === "undefined" || GM_addValueChangeListener === null)) { - $.syncChannel = new BroadcastChannel(g.NAMESPACE + 'sync'); - $.on($.syncChannel, 'message', function(e) { - var cb, key, ref, results, val; - ref = e.data; - results = []; - for (key in ref) { - val = ref[key]; - if ((cb = $.syncing[key])) { - results.push(cb($.dict.json(JSON.stringify(val)), key)); - } - } - return results; - }); - $.sync = function(key, cb) { - return $.syncing[key] = cb; - }; - $.forceSync = function() {}; - $["delete"] = function(keys, cb) { - var key; - if (!(keys instanceof Array)) { - keys = [keys]; - } - return Promise.all((function() { - var j, len, results; - results = []; - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - results.push(GM.deleteValue(g.NAMESPACE + key)); - } - return results; - })()).then(function() { - var items, j, key, len; - items = $.dict(); - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - items[key] = void 0; - } - $.syncChannel.postMessage(items); - return typeof cb === "function" ? cb() : void 0; - }); - }; - $.get = $.oneItemSugar(function(items, cb) { - var key, keys; - keys = Object.keys(items); - return Promise.all((function() { - var j, len, results; - results = []; - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - results.push(GM.getValue(g.NAMESPACE + key)); - } - return results; - })()).then(function(values) { - var i, j, len, val; - for (i = j = 0, len = values.length; j < len; i = ++j) { - val = values[i]; - if (val) { - items[keys[i]] = $.dict.json(val); - } - } - return cb(items); - }); - }); - $.set = $.oneItemSugar(function(items, cb) { - var key, val; - $.securityCheck(items); - return Promise.all((function() { - var results; - results = []; - for (key in items) { - val = items[key]; - results.push(GM.setValue(g.NAMESPACE + key, JSON.stringify(val))); - } - return results; - })()).then(function() { - $.syncChannel.postMessage(items); - return typeof cb === "function" ? cb() : void 0; - }); - }); - $.clear = function(cb) { - return GM.listValues().then(function(keys) { - return $["delete"](keys.map(function(key) { - return key.replace(g.NAMESPACE, ''); - }), cb); - })["catch"](function() { - return $["delete"](Object.keys(Conf).concat(['previousversion', 'QR Size', 'QR.persona']), cb); - }); - }; - } else { - if (typeof GM_deleteValue === "undefined" || GM_deleteValue === null) { - $.perProtocolSettings = true; - } - if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.getValue = GM_getValue; - $.listValues = function() { - return GM_listValues(); - }; - } else if ($.hasStorage) { - $.getValue = function(key) { - return localStorage.getItem(key); - }; - $.listValues = function() { - var key, results; - results = []; - for (key in localStorage) { - if (key.slice(0, g.NAMESPACE.length) === g.NAMESPACE) { - results.push(key); - } - } - return results; - }; - } else { - $.getValue = function() {}; - $.listValues = function() { - return []; - }; - } - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.setValue = GM_setValue; - $.deleteValue = GM_deleteValue; - } else if (typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) { - $.oldValue = $.dict(); - $.setValue = function(key, val) { - GM_setValue(key, val); - if (key in $.syncing) { - $.oldValue[key] = val; - if ($.hasStorage) { - return localStorage.setItem(key, val); - } - } - }; - $.deleteValue = function(key) { - GM_deleteValue(key); - if (key in $.syncing) { - delete $.oldValue[key]; - if ($.hasStorage) { - return localStorage.removeItem(key); - } - } - }; - if (!$.hasStorage) { - $.cantSync = true; - } - } else if ($.hasStorage) { - $.oldValue = $.dict(); - $.setValue = function(key, val) { - if (key in $.syncing) { - $.oldValue[key] = val; - } - return localStorage.setItem(key, val); - }; - $.deleteValue = function(key) { - if (key in $.syncing) { - delete $.oldValue[key]; - } - return localStorage.removeItem(key); - }; - } else { - $.setValue = function() {}; - $.deleteValue = function() {}; - $.cantSync = $.cantSet = true; - } - if (typeof GM_addValueChangeListener !== "undefined" && GM_addValueChangeListener !== null) { - $.sync = function(key, cb) { - return $.syncing[key] = GM_addValueChangeListener(g.NAMESPACE + key, function(key2, oldValue, newValue, remote) { - if (remote) { - if (newValue !== void 0) { - newValue = $.dict.json(newValue); - } - return cb(newValue, key); - } - }); - }; - $.forceSync = function() {}; - } else if ((typeof GM_deleteValue !== "undefined" && GM_deleteValue !== null) || $.hasStorage) { - $.sync = function(key, cb) { - key = g.NAMESPACE + key; - $.syncing[key] = cb; - return $.oldValue[key] = $.getValue(key); - }; - (function() { - var onChange; - onChange = function(arg) { - var cb, key, newValue; - key = arg.key, newValue = arg.newValue; - if (!(cb = $.syncing[key])) { - return; - } - if (newValue != null) { - if (newValue === $.oldValue[key]) { - return; - } - $.oldValue[key] = newValue; - return cb($.dict.json(newValue), key.slice(g.NAMESPACE.length)); - } else { - if ($.oldValue[key] == null) { - return; - } - delete $.oldValue[key]; - return cb(void 0, key.slice(g.NAMESPACE.length)); - } - }; - $.on(window, 'storage', onChange); - return $.forceSync = function(key) { - key = g.NAMESPACE + key; - return onChange({ - key: key, - newValue: $.getValue(key) - }); - }; - })(); - } else { - $.sync = function() {}; - $.forceSync = function() {}; - } - $["delete"] = function(keys) { - var j, key, len; - if (!(keys instanceof Array)) { - keys = [keys]; - } - for (j = 0, len = keys.length; j < len; j++) { - key = keys[j]; - $.deleteValue(g.NAMESPACE + key); - } - }; - $.get = $.oneItemSugar(function(items, cb) { - return $.queueTask($.getSync, items, cb); - }); - $.getSync = function(items, cb) { - var err, key, val2; - for (key in items) { - if ((val2 = $.getValue(g.NAMESPACE + key))) { - try { - items[key] = $.dict.json(val2); - } catch (error) { - err = error; - if (!/^(?:undefined)*$/.test(val2)) { - throw err; - } - } - } - } - return cb(items); - }; - $.set = $.oneItemSugar(function(items, cb) { - $.securityCheck(items); - return $.queueTask(function() { - var key, value; - for (key in items) { - value = items[key]; - $.setValue(g.NAMESPACE + key, JSON.stringify(value)); - } - return typeof cb === "function" ? cb() : void 0; - }); - }); - $.clear = function(cb) { - $["delete"](Object.keys(Conf)); - $["delete"](['previousversion', 'QR Size', 'QR.persona']); - try { - $["delete"]($.listValues().map(function(key) { - return key.replace(g.NAMESPACE, ''); - })); - } catch (error) {} - return typeof cb === "function" ? cb() : void 0; - }; - } - - return $; - -}).call(this); - -$$ = (function() { - var $$, - slice = [].slice; - - $$ = function(selector, root) { - if (root == null) { - root = d.body; - } - return slice.call(root.querySelectorAll(selector)); - }; - - return $$; - -}).call(this); - -CrossOrigin = (function() { - var CrossOrigin, Request; - - CrossOrigin = { - binary: function(url, cb, headers) { - var fallback, gmOptions; - if (headers == null) { - headers = $.dict(); - } - url = url.replace(/^((?:https?:)?\/\/(?:\w+\.)?(?:4chan|4channel|4cdn)\.org)\/adv\//, '$1//adv/'); - fallback = function() { - return $.ajax(url, { - headers: headers, - responseType: 'arraybuffer', - onloadend: function() { - if (this.status && this.response) { - return cb(new Uint8Array(this.response), this.getAllResponseHeaders()); - } else { - return cb(null); - } - } - }); - }; - if (!(((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) != null) || (typeof GM_xmlhttpRequest !== "undefined" && GM_xmlhttpRequest !== null))) { - fallback(); - return; - } - gmOptions = { - method: "GET", - url: url, - headers: headers, - responseType: 'arraybuffer', - overrideMimeType: 'text/plain; charset=x-user-defined', - onload: function(xhr) { - var data, i, r; - if (xhr.response instanceof ArrayBuffer) { - data = new Uint8Array(xhr.response); - } else { - r = xhr.responseText; - data = new Uint8Array(r.length); - i = 0; - while (i < r.length) { - data[i] = r.charCodeAt(i); - i++; - } - } - return cb(data, xhr.responseHeaders); - }, - onerror: function() { - return cb(null); - }, - onabort: function() { - return cb(null); - } - }; - try { - return ((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) || GM_xmlhttpRequest)(gmOptions); - } catch (error) { - return fallback(); - } - }, - file: function(url, cb) { - return CrossOrigin.binary(url, function(data, headers) { - var blob, contentDisposition, contentType, match, mime, name, ref, ref1, ref2, ref3, ref4; - if (data == null) { - return cb(null); - } - name = (ref = url.match(/([^\/?#]+)\/*(?:$|[?#])/)) != null ? ref[1] : void 0; - contentType = (ref1 = headers.match(/Content-Type:\s*(.*)/i)) != null ? ref1[1] : void 0; - contentDisposition = (ref2 = headers.match(/Content-Disposition:\s*(.*)/i)) != null ? ref2[1] : void 0; - mime = (contentType != null ? contentType.match(/[^;]*/)[0] : void 0) || 'application/octet-stream'; - match = (contentDisposition != null ? (ref3 = contentDisposition.match(/\bfilename\s*=\s*"((\\"|[^"])+)"/i)) != null ? ref3[1] : void 0 : void 0) || (contentType != null ? (ref4 = contentType.match(/\bname\s*=\s*"((\\"|[^"])+)"/i)) != null ? ref4[1] : void 0 : void 0); - if (match) { - name = match.replace(/\\"/g, '"'); - } - if (/^text\/plain;\s*charset=x-user-defined$/i.test(mime)) { - mime = $.getOwn(QR.typeFromExtension, name.match(/[^.]*$/)[0].toLowerCase()) || 'application/octet-stream'; - } - blob = new Blob([data], { - type: mime - }); - blob.name = name; - return cb(blob); - }); - }, - Request: Request = (function() { - function Request() {} - - Request.prototype.status = 0; - - Request.prototype.statusText = ''; - - Request.prototype.response = null; - - Request.prototype.responseHeaderString = null; - - Request.prototype.getResponseHeader = function(headerName) { - var header, i, j, key, len, ref, ref1, ref2, val; - if ((this.responseHeaders == null) && (this.responseHeaderString != null)) { - this.responseHeaders = $.dict(); - ref = this.responseHeaderString.split('\r\n'); - for (j = 0, len = ref.length; j < len; j++) { - header = ref[j]; - if ((i = header.indexOf(':')) >= 0) { - key = header.slice(0, i).trim().toLowerCase(); - val = header.slice(i + 1).trim(); - this.responseHeaders[key] = val; - } - } - } - return (ref1 = (ref2 = this.responseHeaders) != null ? ref2[headerName.toLowerCase()] : void 0) != null ? ref1 : null; - }; - - Request.prototype.abort = function() {}; - - Request.prototype.onloadend = function() {}; - - return Request; - - })(), - ajax: function(url, options) { - var gmOptions, gmReq, headers, onloadend, req, responseType, timeout; - if (options == null) { - options = {}; - } - onloadend = options.onloadend, timeout = options.timeout, responseType = options.responseType, headers = options.headers; - if (responseType == null) { - responseType = 'json'; - } - if (!(((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) != null) || (typeof GM_xmlhttpRequest !== "undefined" && GM_xmlhttpRequest !== null))) { - return $.ajax(url, options); - } - req = new CrossOrigin.Request(); - req.onloadend = onloadend; - gmOptions = { - method: 'GET', - url: url, - headers: headers, - timeout: timeout, - onload: function(xhr) { - var response; - try { - response = (function() { - switch (responseType) { - case 'json': - if (xhr.responseText) { - return JSON.parse(xhr.responseText); - } else { - return null; - } - break; - default: - return xhr.responseText; - } - })(); - $.extend(req, { - response: response, - status: xhr.status, - statusText: xhr.statusText, - responseHeaderString: xhr.responseHeaders - }); - } catch (error) {} - return req.onloadend(); - }, - onerror: function() { - return req.onloadend(); - }, - onabort: function() { - return req.onloadend(); - }, - ontimeout: function() { - return req.onloadend(); - } - }; - try { - gmReq = ((typeof GM !== "undefined" && GM !== null ? GM.xmlHttpRequest : void 0) || GM_xmlhttpRequest)(gmOptions); - } catch (error) { - return $.ajax(url, options); - } - if (gmReq && typeof gmReq.abort === 'function') { - req.abort = function() { - try { - return gmReq.abort(); - } catch (error) {} - }; - } - return req; - }, - cache: function(url, cb) { - return $.cache(url, cb, { - ajax: CrossOrigin.ajax - }); - }, - permission: function(cb) { - return cb(); - } - }; - - return CrossOrigin; - -}).call(this); - -Board = (function() { - var Board; - - Board = (function() { - Board.prototype.toString = function() { - return this.ID; - }; - - function Board(ID) { - var ref; - this.ID = ID; - this.boardID = this.ID; - this.siteID = g.SITE.ID; - this.threads = new SimpleDict(); - this.posts = new SimpleDict(); - this.config = ((ref = BoardConfig.boards) != null ? ref[this.ID] : void 0) || {}; - g.boards[this] = this; - } - - Board.prototype.cooldowns = function() { - var c, c2, i, key, len, ref; - c2 = (this.config || {}).cooldowns || {}; - c = { - thread: c2.threads || 0, - reply: c2.replies || 0, - image: c2.images || 0, - thread_global: 300 - }; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - ref = ['reply', 'image']; - for (i = 0, len = ref.length; i < len; i++) { - key = ref[i]; - c[key] = Math.ceil(c[key] / 2); - } - } - return c; - }; - - return Board; - - })(); - - return Board; - -}).call(this); - -Callbacks = (function() { - var Callbacks; - - Callbacks = (function() { - Callbacks.Post = new Callbacks('Post'); - - Callbacks.Thread = new Callbacks('Thread'); - - Callbacks.CatalogThread = new Callbacks('Catalog Thread'); - - Callbacks.CatalogThreadNative = new Callbacks('Catalog Thread'); - - function Callbacks(type) { - this.type = type; - this.keys = []; - } - - Callbacks.prototype.push = function(arg) { - var cb, name; - name = arg.name, cb = arg.cb; - if (!this[name]) { - this.keys.push(name); - } - return this[name] = cb; - }; - - Callbacks.prototype.execute = function(node, keys, force) { - var err, errors, i, len, name, ref, ref1, ref2; - if (keys == null) { - keys = this.keys; - } - if (force == null) { - force = false; - } - if (node.callbacksExecuted && !force) { - return; - } - node.callbacksExecuted = true; - for (i = 0, len = keys.length; i < len; i++) { - name = keys[i]; - try { - if ((ref = this[name]) != null) { - ref.call(node); - } - } catch (error) { - err = error; - if (!errors) { - errors = []; - } - errors.push({ - message: ['"', name, '" crashed on node ', this.type, ' No.', node.ID, ' (', node.board, ').'].join(''), - error: err, - html: (ref1 = node.nodes) != null ? (ref2 = ref1.root) != null ? ref2.outerHTML : void 0 : void 0 - }); - } - } - if (errors) { - return Main.handleErrors(errors); - } - }; - - return Callbacks; - - })(); - - return Callbacks; - -}).call(this); - -CatalogThread = (function() { - var CatalogThread; - - CatalogThread = (function() { - CatalogThread.prototype.toString = function() { - return this.ID; - }; - - function CatalogThread(root, thread) { - var post; - this.thread = thread; - this.ID = this.thread.ID; - this.board = this.thread.board; - post = this.thread.OP.nodes.post; - this.nodes = { - root: root, - thumb: $('.catalog-thumb', post), - icons: $('.catalog-icons', post), - postCount: $('.post-count', post), - fileCount: $('.file-count', post), - pageCount: $('.page-count', post), - replies: null - }; - this.thread.catalogView = this; - } - - return CatalogThread; - - })(); - - return CatalogThread; - -}).call(this); - -CatalogThreadNative = (function() { - var CatalogThreadNative; - - CatalogThreadNative = (function() { - CatalogThreadNative.prototype.toString = function() { - return this.ID; - }; - - function CatalogThreadNative(root) { - this.nodes = { - root: root, - thumb: $(g.SITE.selectors.catalog.thumb, root) - }; - this.siteID = g.SITE.ID; - this.boardID = this.nodes.thumb.parentNode.pathname.split(/\/+/)[1]; - this.board = g.boards[this.boardID] || new Board(this.boardID); - this.ID = this.threadID = +(root.dataset.id || root.id).match(/\d*$/)[0]; - this.thread = this.board.threads.get(this.ID) || new Thread(this.ID, this.board); - } - - return CatalogThreadNative; - - })(); - - return CatalogThreadNative; - -}).call(this); - -Connection = (function() { - var Connection, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - Connection = (function() { - function Connection(target, origin, cb) { - this.target = target; - this.origin = origin; - this.cb = cb != null ? cb : {}; - this.onMessage = bind(this.onMessage, this); - this.send = bind(this.send, this); - $.on(window, 'message', this.onMessage); - } - - Connection.prototype.targetWindow = function() { - if (this.target instanceof window.HTMLIFrameElement) { - return this.target.contentWindow; - } else { - return this.target; - } - }; - - Connection.prototype.send = function(data) { - return this.targetWindow().postMessage("" + g.NAMESPACE + (JSON.stringify(data)), this.origin); - }; - - Connection.prototype.onMessage = function(e) { - var data, type, value; - if (!(e.source === this.targetWindow() && e.origin === this.origin && typeof e.data === 'string' && e.data.slice(0, g.NAMESPACE.length) === g.NAMESPACE)) { - return; - } - data = JSON.parse(e.data.slice(g.NAMESPACE.length)); - for (type in data) { - value = data[type]; - if ($.hasOwn(this.cb, type)) { - this.cb[type](value); - } - } - }; - - return Connection; - - })(); - - return Connection; - -}).call(this); - -DataBoard = (function() { - var DataBoard, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - DataBoard = (function() { - DataBoard.keys = ['hiddenThreads', 'hiddenPosts', 'lastReadPosts', 'yourPosts', 'watchedThreads', 'watcherLastModified', 'customTitles']; - - function DataBoard(key1, sync, dontClean) { - var init; - this.key = key1; - this.onSync = bind(this.onSync, this); - this.initData(Conf[this.key]); - $.sync(this.key, this.onSync); - if (!dontClean) { - this.clean(); - } - if (!sync) { - return; - } - init = (function(_this) { - return function() { - $.off(d, '4chanXInitFinished', init); - return _this.sync = sync; - }; - })(this); - $.on(d, '4chanXInitFinished', init); - } - - DataBoard.prototype.initData = function(data1) { - var base, boards, lastChecked, name, ref; - this.data = data1; - if (this.data.boards) { - ref = this.data, boards = ref.boards, lastChecked = ref.lastChecked; - this.data['4chan.org'] = { - boards: boards, - lastChecked: lastChecked - }; - delete this.data.boards; - delete this.data.lastChecked; - } - return (base = this.data)[name = g.SITE.ID] || (base[name] = { - boards: $.dict() - }); - }; - - DataBoard.prototype.changes = []; - - DataBoard.prototype.save = function(change, cb) { - change(); - this.changes.push(change); - return $.get(this.key, { - boards: $.dict() - }, (function(_this) { - return function(items) { - var i, len, needSync, ref; - if (!_this.changes.length) { - return; - } - needSync = (items[_this.key].version || 0) > (_this.data.version || 0); - if (needSync) { - _this.initData(items[_this.key]); - ref = _this.changes; - for (i = 0, len = ref.length; i < len; i++) { - change = ref[i]; - change(); - } - } - _this.changes = []; - _this.data.version = (_this.data.version || 0) + 1; - return $.set(_this.key, _this.data, function() { - if (needSync) { - if (typeof _this.sync === "function") { - _this.sync(); - } - } - return typeof cb === "function" ? cb() : void 0; - }); - }; - })(this)); - }; - - DataBoard.prototype.forceSync = function(cb) { - return $.get(this.key, { - boards: $.dict() - }, (function(_this) { - return function(items) { - var change, i, len, ref; - if ((items[_this.key].version || 0) > (_this.data.version || 0)) { - _this.initData(items[_this.key]); - ref = _this.changes; - for (i = 0, len = ref.length; i < len; i++) { - change = ref[i]; - change(); - } - if (typeof _this.sync === "function") { - _this.sync(); - } - } - return typeof cb === "function" ? cb() : void 0; - }; - })(this)); - }; - - DataBoard.prototype["delete"] = function(arg, cb) { - var boardID, postID, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID; - siteID || (siteID = g.SITE.ID); - if (!this.data[siteID]) { - return; - } - return this.save((function(_this) { - return function() { - var ref; - if (postID) { - if (!((ref = _this.data[siteID].boards[boardID]) != null ? ref[threadID] : void 0)) { - return; - } - delete _this.data[siteID].boards[boardID][threadID][postID]; - return _this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }); - } else if (threadID) { - if (!_this.data[siteID].boards[boardID]) { - return; - } - delete _this.data[siteID].boards[boardID][threadID]; - return _this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - } else { - return delete _this.data[siteID].boards[boardID]; - } - }; - })(this), cb); - }; - - DataBoard.prototype.deleteIfEmpty = function(arg) { - var boardID, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID; - if (!this.data[siteID]) { - return; - } - if (threadID) { - if (!Object.keys(this.data[siteID].boards[boardID][threadID]).length) { - delete this.data[siteID].boards[boardID][threadID]; - return this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - } - } else if (!Object.keys(this.data[siteID].boards[boardID]).length) { - return delete this.data[siteID].boards[boardID]; - } - }; - - DataBoard.prototype.set = function(data, cb) { - return this.save((function(_this) { - return function() { - return _this.setUnsafe(data); - }; - })(this), cb); - }; - - DataBoard.prototype.setUnsafe = function(arg) { - var base, base1, base2, base3, boardID, postID, siteID, threadID, val; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; - siteID || (siteID = g.SITE.ID); - (base = this.data)[siteID] || (base[siteID] = { - boards: $.dict() - }); - if (postID !== void 0) { - return ((base1 = ((base2 = this.data[siteID].boards)[boardID] || (base2[boardID] = $.dict())))[threadID] || (base1[threadID] = $.dict()))[postID] = val; - } else if (threadID !== void 0) { - return ((base3 = this.data[siteID].boards)[boardID] || (base3[boardID] = $.dict()))[threadID] = val; - } else { - return this.data[siteID].boards[boardID] = val; - } - }; - - DataBoard.prototype.extend = function(arg, cb) { - var boardID, postID, siteID, threadID, val; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, val = arg.val; - return this.save((function(_this) { - return function() { - var key, oldVal, subVal; - oldVal = _this.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: postID, - defaultValue: $.dict() - }); - for (key in val) { - subVal = val[key]; - if (typeof subVal === 'undefined') { - delete oldVal[key]; - } else { - oldVal[key] = subVal; - } - } - return _this.setUnsafe({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: postID, - val: oldVal - }); - }; - })(this), cb); - }; - - DataBoard.prototype.setLastChecked = function(key) { - if (key == null) { - key = 'lastChecked'; - } - return this.save((function(_this) { - return function() { - return _this.data[key] = Date.now(); - }; - })(this)); - }; - - DataBoard.prototype.get = function(arg) { - var ID, board, boardID, defaultValue, i, len, postID, ref, siteID, thread, threadID, val; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID, defaultValue = arg.defaultValue; - siteID || (siteID = g.SITE.ID); - if (board = (ref = this.data[siteID]) != null ? ref.boards[boardID] : void 0) { - if (threadID == null) { - if (postID != null) { - for (thread = i = 0, len = board.length; i < len; thread = ++i) { - ID = board[thread]; - if (postID in thread) { - val = thread[postID]; - break; - } - } - } else { - val = board; - } - } else if (thread = board[threadID]) { - val = postID != null ? thread[postID] : thread; - } - } - return val || defaultValue; - }; - - DataBoard.prototype.clean = function() { - var boardID, now, ref, ref1, siteID, val; - siteID = g.SITE.ID; - ref = this.data[siteID].boards; - for (boardID in ref) { - val = ref[boardID]; - this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - } - now = Date.now(); - if (!((now - 2 * $.HOUR < (ref1 = this.data[siteID].lastChecked || 0) && ref1 <= now))) { - this.data[siteID].lastChecked = now; - for (boardID in this.data[siteID].boards) { - this.ajaxClean(boardID); - } - } - }; - - DataBoard.prototype.ajaxClean = function(boardID) { - var base, siteID, that, threadsList; - that = this; - siteID = g.SITE.ID; - threadsList = typeof (base = g.SITE.urls).threadsListJSON === "function" ? base.threadsListJSON({ - siteID: siteID, - boardID: boardID - }) : void 0; - if (!threadsList) { - return; - } - return $.cache(threadsList, function() { - var archiveList, base1, response1; - if (this.status !== 200) { - return; - } - archiveList = typeof (base1 = g.SITE.urls).archiveListJSON === "function" ? base1.archiveListJSON({ - siteID: siteID, - boardID: boardID - }) : void 0; - if (!archiveList) { - return that.ajaxCleanParse(boardID, this.response); - } - response1 = this.response; - return $.cache(archiveList, function() { - if (!(this.status === 200 || (!g.SITE.archivedBoardsKnown && this.status === 404))) { - return; - } - return that.ajaxCleanParse(boardID, response1, this.response); - }); - }); - }; - - DataBoard.prototype.ajaxCleanParse = function(boardID, response1, response2) { - var ID, board, i, j, k, len, len1, len2, page, ref, siteID, thread, threads; - siteID = g.SITE.ID; - if (!(board = this.data[siteID].boards[boardID])) { - return; - } - threads = $.dict(); - if (response1) { - for (i = 0, len = response1.length; i < len; i++) { - page = response1[i]; - ref = page.threads; - for (j = 0, len1 = ref.length; j < len1; j++) { - thread = ref[j]; - ID = thread.no; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - } - if (response2) { - for (k = 0, len2 = response2.length; k < len2; k++) { - ID = response2[k]; - if (ID in board) { - threads[ID] = board[ID]; - } - } - } - this.data[siteID].boards[boardID] = threads; - this.deleteIfEmpty({ - siteID: siteID, - boardID: boardID - }); - return $.set(this.key, this.data); - }; - - DataBoard.prototype.onSync = function(data) { - if (!((data.version || 0) > (this.data.version || 0))) { - return; - } - this.initData(data); - return typeof this.sync === "function" ? this.sync() : void 0; - }; - - return DataBoard; - - })(); - - return DataBoard; - -}).call(this); - -Fetcher = (function() { - var Fetcher, - slice = [].slice; - - Fetcher = (function() { - function Fetcher(boardID1, threadID, postID1, root, quoter) { - var board, post, ref, that, thread; - this.boardID = boardID1; - this.threadID = threadID; - this.postID = postID1; - this.root = root; - this.quoter = quoter; - if (post = g.posts.get(this.boardID + "." + this.postID)) { - this.insert(post); - return; - } - if ((post = (ref = Index.replyData) != null ? ref[this.boardID + "." + this.postID] : void 0) && (thread = g.threads.get(this.boardID + "." + this.threadID))) { - board = g.boards[this.boardID]; - post = new Post(g.SITE.Build.postFromObject(post, this.boardID), thread, board, { - isFetchedQuote: true - }); - Main.callbackNodes('Post', [post]); - this.insert(post); - return; - } - this.root.textContent = "Loading post No." + this.postID + "..."; - if (this.threadID) { - that = this; - $.cache(g.SITE.urls.threadJSON({ - boardID: this.boardID, - threadID: this.threadID - }), function(arg) { - var isCached; - isCached = arg.isCached; - return that.fetchedPost(this, isCached); - }); - } else { - this.archivedPost(); - } - } - - Fetcher.prototype.insert = function(post) { - var boardID, clone, cssVersion, k, len, nodes, postID, quote, ref, ref1, ref2; - if (!this.root.parentNode) { - return; - } - this.quoter || (this.quoter = post); - clone = post.addClone(this.quoter.context, $.hasClass(this.root, 'dialog')); - Main.callbackNodes('Post', [clone]); - nodes = clone.nodes; - $.rmAll(nodes.root); - $.add(nodes.root, nodes.post); - ref = clone.nodes.quotelinks.concat(slice.call(clone.nodes.backlinks)); - for (k = 0, len = ref.length; k < len; k++) { - quote = ref[k]; - ref1 = Get.postDataFromLink(quote), boardID = ref1.boardID, postID = ref1.postID; - if (postID === this.quoter.ID && boardID === this.quoter.board.ID) { - $.addClass(quote, 'forwardlink'); - } - } - if (clone.nodes.flag && !(Fetcher.flagCSS || (Fetcher.flagCSS = $('link[href^="//s.4cdn.org/css/flags."]')))) { - cssVersion = ((ref2 = $('link[href^="//s.4cdn.org/css/"]')) != null ? ref2.href.match(/\d+(?=\.css$)|$/)[0] : void 0) || Date.now(); - Fetcher.flagCSS = $.el('link', { - rel: 'stylesheet', - href: "//s.4cdn.org/css/flags." + cssVersion + ".css" - }); - $.add(d.head, Fetcher.flagCSS); - } - $.rmAll(this.root); - $.add(this.root, nodes.root); - return $.event('PostsInserted', null, this.root); - }; - - Fetcher.prototype.fetchedPost = function(req, isCached) { - var api, board, k, len, post, posts, status, that, thread; - if (post = g.posts.get(this.boardID + "." + this.postID)) { - this.insert(post); - return; - } - status = req.status; - if (status !== 200) { - if (status && this.archivedPost()) { - return; - } - $.addClass(this.root, 'warning'); - this.root.textContent = status === 404 ? "Thread No." + this.threadID + " 404'd." : !status ? 'Connection Error' : "Error " + req.statusText + " (" + req.status + ")."; - return; - } - posts = req.response.posts; - g.SITE.Build.spoilerRange[this.boardID] = posts[0].custom_spoiler; - for (k = 0, len = posts.length; k < len; k++) { - post = posts[k]; - if (post.no === this.postID) { - break; - } - } - if (post.no !== this.postID) { - if (isCached) { - api = g.SITE.urls.threadJSON({ - boardID: this.boardID, - threadID: this.threadID - }); - $.cleanCache(function(url) { - return url === api; - }); - that = this; - $.cache(api, function() { - return that.fetchedPost(this, false); - }); - return; - } - if (this.archivedPost()) { - return; - } - $.addClass(this.root, 'warning'); - this.root.textContent = "Post No." + this.postID + " was not found."; - return; - } - board = g.boards[this.boardID] || new Board(this.boardID); - thread = g.threads.get(this.boardID + "." + this.threadID) || new Thread(this.threadID, board); - post = new Post(g.SITE.Build.postFromObject(post, this.boardID), thread, board, { - isFetchedQuote: true - }); - Main.callbackNodes('Post', [post]); - return this.insert(post); - }; - - Fetcher.prototype.archivedPost = function() { - var archive, encryptionOK, that, url; - if (!Conf['Resurrect Quotes']) { - return false; - } - if (!(url = Redirect.to('post', { - boardID: this.boardID, - postID: this.postID - }))) { - return false; - } - archive = Redirect.data.post[this.boardID]; - encryptionOK = /^https:\/\//.test(url) || location.protocol === 'http:'; - if (encryptionOK || Conf['Exempt Archives from Encryption']) { - that = this; - CrossOrigin.cache(url, function() { - var key, media, ref, ref1; - if (!encryptionOK && ((ref = this.response) != null ? ref.media : void 0)) { - media = this.response.media; - for (key in media) { - if (/_link$/.test(key)) { - if (!((ref1 = $.getOwn(media, key)) != null ? ref1.match(/^http:\/\//) : void 0)) { - delete media[key]; - } - } - } - } - return that.parseArchivedPost(this.response, url, archive); - }); - return true; - } - return false; - }; - - Fetcher.prototype.parseArchivedPost = function(data, url, archive) { - var board, comment, greentext, i, j, media_link, o, post, ref, tag, text, text2, thread, thumb_link; - if (post = g.posts.get(this.boardID + "." + this.postID)) { - this.insert(post); - return; - } - if (data == null) { - $.addClass(this.root, 'warning'); - this.root.textContent = "Error fetching Post No." + this.postID + " from " + archive.name + "."; - return; - } - if (data.error) { - $.addClass(this.root, 'warning'); - this.root.textContent = data.error; - return; - } - comment = (data.comment || '').split(/(\n|\[\/?(?:b|spoiler|code|moot|banned|fortune(?: color="#\w+")?|i|red|green|blue)\])/); - comment = (function() { - var k, len, results; - results = []; - for (i = k = 0, len = comment.length; k < len; i = ++k) { - text = comment[i]; - if (i % 2 === 1) { - tag = this.archiveTags[text.replace(/\ .*\]/, ']')]; - if (typeof tag === 'function') { - results.push(tag(text)); - } else { - results.push(tag); - } - } else { - greentext = text[0] === '>'; - text = text.replace(/(\[\/?[a-z]+):lit(\])/g, '$1$2'); - text = (function() { - var l, len1, ref, results1; - ref = text.split(/(>>(?:>\/[a-z\d]+\/)?\d+)/g); - results1 = []; - for (j = l = 0, len1 = ref.length; l < len1; j = ++l) { - text2 = ref[j]; - results1.push({innerHTML: ((j % 2) ? "" + E(text2) + "" : E(text2))}); - } - return results1; - })(); - text = {innerHTML: ((greentext) ? "" + E.cat(text) + "" : E.cat(text))}; - results.push(text); - } - } - return results; - }).call(this); - comment = {innerHTML: E.cat(comment)}; - this.threadID = +data.thread_num; - o = { - ID: this.postID, - threadID: this.threadID, - boardID: this.boardID, - isReply: this.postID !== this.threadID - }; - o.info = { - subject: data.title, - email: data.email, - name: data.name || '', - tripcode: data.trip, - capcode: (function() { - switch (data.capcode) { - case 'M': - return 'Mod'; - case 'A': - return 'Admin'; - case 'D': - return 'Developer'; - case 'V': - return 'Verified'; - case 'F': - return 'Founder'; - case 'G': - return 'Manager'; - } - })(), - uniqueID: data.poster_hash, - flagCode: data.poster_country, - flagCodeTroll: data.troll_country_code, - flag: data.poster_country_name || data.troll_country_name, - dateUTC: data.timestamp, - dateText: data.fourchan_date, - commentHTML: comment - }; - if (o.info.capcode) { - delete o.info.uniqueID; - } - if (data.media && !!+data.media.banned) { - o.fileDeleted = true; - } else if ((ref = data.media) != null ? ref.media_filename : void 0) { - thumb_link = data.media.thumb_link; - if ((thumb_link != null ? thumb_link[0] : void 0) === '/') { - thumb_link = url.split('/', 3).join('/') + thumb_link; - } - if (!Redirect.securityCheck(thumb_link)) { - thumb_link = ''; - } - media_link = Redirect.to('file', { - boardID: this.boardID, - filename: data.media.media_orig - }); - if (!Redirect.securityCheck(media_link)) { - media_link = ''; - } - o.file = { - name: data.media.media_filename, - url: media_link || (this.boardID === 'f' ? location.protocol + "//" + (ImageHost.flashHost()) + "/" + this.boardID + "/" + (encodeURIComponent(E(data.media.media_filename))) : location.protocol + "//" + (ImageHost.host()) + "/" + this.boardID + "/" + data.media.media_orig), - height: data.media.media_h, - width: data.media.media_w, - MD5: data.media.media_hash, - size: $.bytesToString(data.media.media_size), - thumbURL: thumb_link || (location.protocol + "//" + (ImageHost.thumbHost()) + "/" + this.boardID + "/" + data.media.preview_orig), - theight: data.media.preview_h, - twidth: data.media.preview_w, - isSpoiler: data.media.spoiler === '1' - }; - if (!/\.pdf$/.test(o.file.url)) { - o.file.dimensions = o.file.width + "x" + o.file.height; - } - if (this.boardID === 'f' && data.media.exif) { - o.file.tag = JSON.parse(data.media.exif).Tag; - } - } - o.extra = $.dict(); - board = g.boards[this.boardID] || new Board(this.boardID); - thread = g.threads.get(this.boardID + "." + this.threadID) || new Thread(this.threadID, board); - post = new Post(g.SITE.Build.post(o), thread, board, { - isFetchedQuote: true - }); - post.kill(); - if (post.file) { - post.file.thumbURL = o.file.thumbURL; - } - Main.callbackNodes('Post', [post]); - return this.insert(post); - }; - - Fetcher.prototype.archiveTags = { - '\n': {innerHTML: "
    "}, - '[b]': {innerHTML: ""}, - '[/b]': {innerHTML: ""}, - '[spoiler]': {innerHTML: ""}, - '[/spoiler]': {innerHTML: ""}, - '[code]': {innerHTML: "
    "},
    -      '[/code]': {innerHTML: "
    "}, - '[moot]': {innerHTML: "
    "}, - '[/moot]': {innerHTML: "
    "}, - '[banned]': {innerHTML: ""}, - '[/banned]': {innerHTML: ""}, - '[fortune]': function(text) { - return {innerHTML: ""}; - }, - '[/fortune]': {innerHTML: ""}, - '[i]': {innerHTML: ""}, - '[/i]': {innerHTML: ""}, - '[red]': {innerHTML: ""}, - '[/red]': {innerHTML: ""}, - '[green]': {innerHTML: ""}, - '[/green]': {innerHTML: ""}, - '[blue]': {innerHTML: ""}, - '[/blue]': {innerHTML: ""} - }; - - return Fetcher; - - })(); - - return Fetcher; - -}).call(this); - -Notice = (function() { - var Notice, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - Notice = (function() { - function Notice(type, content, timeout, onclose) { - this.timeout = timeout; - this.onclose = onclose; - this.close = bind(this.close, this); - this.add = bind(this.add, this); - this.el = $.el('div', {innerHTML: "
    "}); - this.el.style.opacity = 0; - this.setType(type); - $.on(this.el.firstElementChild, 'click', this.close); - if (typeof content === 'string') { - content = $.tn(content); - } - $.add(this.el.lastElementChild, content); - $.ready(this.add); - } - - Notice.prototype.setType = function(type) { - return this.el.className = "notification " + type; - }; - - Notice.prototype.add = function() { - if (this.closed) { - return; - } - if (d.hidden) { - $.on(d, 'visibilitychange', this.add); - return; - } - $.off(d, 'visibilitychange', this.add); - $.add(Header.noticesRoot, this.el); - this.el.clientHeight; - this.el.style.opacity = 1; - if (this.timeout) { - return setTimeout(this.close, this.timeout * $.SECOND); - } - }; - - Notice.prototype.close = function() { - this.closed = true; - $.off(d, 'visibilitychange', this.add); - $.rm(this.el); - return typeof this.onclose === "function" ? this.onclose() : void 0; - }; - - return Notice; - - })(); - - return Notice; - -}).call(this); - -Post = (function() { - var Post, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Post = (function() { - Post.prototype.toString = function() { - return this.ID; - }; - - function Post(root, thread, board, flags) { - var clone, j, k, key, len, len1, ref, ref1, ref10, ref11, ref12, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, selector; - this.thread = thread; - this.board = board; - if (flags == null) { - flags = {}; - } - $.extend(this, flags); - this.ID = +root.id.match(/\d*$/)[0]; - this.postID = this.ID; - this.threadID = this.thread.ID; - this.boardID = this.board.ID; - this.siteID = g.SITE.ID; - this.fullID = this.board + "." + this.ID; - this.context = this; - this.isReply = this.ID !== this.threadID; - root.dataset.fullID = this.fullID; - this.nodes = this.parseNodes(root); - if (!this.isReply) { - this.thread.OP = this; - ref = ['isSticky', 'isClosed', 'isArchived']; - for (j = 0, len = ref.length; j < len; j++) { - key = ref[j]; - if ((selector = g.SITE.selectors.icons[key])) { - this.thread[key] = !!$(selector, this.nodes.info); - } - } - if (this.thread.isArchived) { - this.thread.isClosed = true; - this.thread.kill(); - } - } - this.info = { - subject: ((ref1 = this.nodes.subject) != null ? ref1.textContent : void 0) || void 0, - name: (ref2 = this.nodes.name) != null ? ref2.textContent : void 0, - email: this.nodes.email ? decodeURIComponent(this.nodes.email.href.replace(/^mailto:/, '')) : void 0, - tripcode: (ref3 = this.nodes.tripcode) != null ? ref3.textContent : void 0, - uniqueID: (ref4 = this.nodes.uniqueID) != null ? ref4.textContent : void 0, - capcode: (ref5 = this.nodes.capcode) != null ? ref5.textContent.replace('## ', '') : void 0, - pass: (ref6 = this.nodes.pass) != null ? ref6.title.match(/\d*$/)[0] : void 0, - flagCode: (ref7 = this.nodes.flag) != null ? (ref8 = ref7.className.match(/flag-(\w+)/)) != null ? ref8[1].toUpperCase() : void 0 : void 0, - flagCodeTroll: (ref9 = this.nodes.flag) != null ? (ref10 = ref9.className.match(/bfl-(\w+)/)) != null ? ref10[1].toUpperCase() : void 0 : void 0, - flag: (ref11 = this.nodes.flag) != null ? ref11.title : void 0, - date: this.nodes.date ? g.SITE.parseDate(this.nodes.date) : void 0 - }; - if (Conf['Anonymize']) { - this.info.nameBlock = 'Anonymous'; - } else { - this.info.nameBlock = ((this.info.name || '') + " " + (this.info.tripcode || '')).trim(); - } - if (this.info.capcode) { - this.info.nameBlock += " ## " + this.info.capcode; - } - if (this.info.uniqueID) { - this.info.nameBlock += " (ID: " + this.info.uniqueID + ")"; - } - this.parseComment(); - this.parseQuotes(); - this.parseFiles(); - this.isDead = false; - this.isHidden = false; - this.clones = []; - if (g.posts.get(this.fullID)) { - this.isRebuilt = true; - this.clones = g.posts.get(this.fullID).clones; - ref12 = this.clones; - for (k = 0, len1 = ref12.length; k < len1; k++) { - clone = ref12[k]; - clone.origin = this; - } - } - if (!this.isFetchedQuote && this.ID > this.thread.lastPost) { - this.thread.lastPost = this.ID; - } - this.board.posts.push(this.ID, this); - this.thread.posts.push(this.ID, this); - g.posts.push(this.fullID, this); - } - - Post.prototype.parseNodes = function(root) { - var base, info, key, nodes, post, ref, s, selector; - s = g.SITE.selectors; - post = $(s.post, root) || root; - info = $(s.infoRoot, post); - nodes = { - root: root, - bottom: this.isReply || !g.SITE.isOPContainerThread ? root : $(s.opBottom, root), - post: post, - info: info, - comment: $(s.comment, post), - quotelinks: [], - archivelinks: [], - embedlinks: [] - }; - ref = s.info; - for (key in ref) { - selector = ref[key]; - nodes[key] = $(selector, info); - } - if (typeof (base = g.SITE).parseNodes === "function") { - base.parseNodes(this, nodes); - } - nodes.uniqueIDRoot || (nodes.uniqueIDRoot = nodes.uniqueID); - if ($.engine === 'edge') { - Object.defineProperty(nodes, 'backlinks', { - configurable: true, - enumerable: true, - get: function() { - return post.getElementsByClassName('backlink'); - } - }); - } else { - nodes.backlinks = post.getElementsByClassName('backlink'); - } - return nodes; - }; - - Post.prototype.parseComment = function() { - var base, bq; - this.nodes.comment.normalize(); - this.nodes.commentClean = bq = this.nodes.comment.cloneNode(true); - if (typeof (base = g.SITE).cleanComment === "function") { - base.cleanComment(bq); - } - return this.info.comment = this.nodesToText(bq); - }; - - Post.prototype.commentDisplay = function() { - var base, bq; - bq = this.nodes.commentClean.cloneNode(true); - if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { - this.cleanSpoilers(bq); - } - if (typeof (base = g.SITE).cleanCommentDisplay === "function") { - base.cleanCommentDisplay(bq); - } - return this.nodesToText(bq).trim().replace(/\s+$/gm, ''); - }; - - Post.prototype.commentOrig = function() { - var base, bq; - bq = this.nodes.commentClean.cloneNode(true); - if (typeof (base = g.SITE).insertTags === "function") { - base.insertTags(bq); - } - return this.nodesToText(bq); - }; - - Post.prototype.nodesToText = function(bq) { - var i, node, nodes, text; - text = ""; - nodes = $.X('.//br|.//text()', bq); - i = 0; - while (node = nodes.snapshotItem(i++)) { - text += node.data || '\n'; - } - return text; - }; - - Post.prototype.cleanSpoilers = function(bq) { - var j, len, node, spoilers; - spoilers = $$(g.SITE.selectors.spoiler, bq); - for (j = 0, len = spoilers.length; j < len; j++) { - node = spoilers[j]; - $.replace(node, $.tn('[spoiler]')); - } - }; - - Post.prototype.parseQuotes = function() { - var j, len, quotelink, ref; - this.quotes = []; - ref = $$(g.SITE.selectors.quotelink, this.nodes.comment); - for (j = 0, len = ref.length; j < len; j++) { - quotelink = ref[j]; - this.parseQuote(quotelink); - } - }; - - Post.prototype.parseQuote = function(quotelink) { - var fullID, match; - match = quotelink.href.match(g.SITE.regexp.quotelink); - if (!(match || (this.isClone && quotelink.dataset.postID))) { - return; - } - this.nodes.quotelinks.push(quotelink); - if (this.isClone) { - return; - } - fullID = match[1] + "." + match[3]; - if (indexOf.call(this.quotes, fullID) < 0) { - return this.quotes.push(fullID); - } - }; - - Post.prototype.parseFiles = function() { - var docIndex, file, fileRoot, fileRoots, index, j, len; - this.files = []; - fileRoots = this.fileRoots(); - index = 0; - for (docIndex = j = 0, len = fileRoots.length; j < len; docIndex = ++j) { - fileRoot = fileRoots[docIndex]; - if ((file = this.parseFile(fileRoot))) { - file.index = index++; - file.docIndex = docIndex; - this.files.push(file); - } - } - if (this.files.length) { - return this.file = this.files[0]; - } - }; - - Post.prototype.fileRoots = function() { - var roots; - if (g.SITE.selectors.multifile) { - roots = $$(g.SITE.selectors.multifile, this.nodes.root); - if (roots.length) { - return roots; - } - } - return [this.nodes.root]; - }; - - Post.prototype.parseFile = function(fileRoot) { - var file, key, ref, ref1, selector, size, unit; - file = {}; - ref = g.SITE.selectors.file; - for (key in ref) { - selector = ref[key]; - file[key] = $(selector, fileRoot); - } - file.thumbLink = (ref1 = file.thumb) != null ? ref1.parentNode : void 0; - if (!(file.text && file.link)) { - return; - } - if (!g.SITE.parseFile(this, file)) { - return; - } - $.extend(file, { - url: file.link.href, - isImage: $.isImage(file.link.href), - isVideo: $.isVideo(file.link.href) - }); - size = +file.size.match(/[\d.]+/)[0]; - unit = ['B', 'KB', 'MB', 'GB'].indexOf(file.size.match(/\w+$/)[0]); - while (unit-- > 0) { - size *= 1024; - } - file.sizeInBytes = size; - return file; - }; - - Post.deadMark = $.el('span', { - textContent: '\u00A0(Dead)', - className: 'qmark-dead' - }); - - Post.prototype.kill = function(file, index) { - var clone, j, k, len, len1, quotelink, ref, ref1, strong; - if (index == null) { - index = 0; - } - if (file) { - if (this.isDead || this.files[index].isDead) { - return; - } - this.files[index].isDead = true; - $.addClass(this.nodes.root, 'deleted-file'); - } else { - if (this.isDead) { - return; - } - this.isDead = true; - $.rmClass(this.nodes.root, 'deleted-file'); - $.addClass(this.nodes.root, 'deleted-post'); - } - if (!(strong = $('strong.warning', this.nodes.info))) { - strong = $.el('strong', { - className: 'warning' - }); - $.after($('input', this.nodes.info), strong); - } - strong.textContent = file ? '[File deleted]' : '[Deleted]'; - if (this.isClone) { - return; - } - ref = this.clones; - for (j = 0, len = ref.length; j < len; j++) { - clone = ref[j]; - clone.kill(file, index); - } - if (file) { - return; - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (k = 0, len1 = ref1.length; k < len1; k++) { - quotelink = ref1[k]; - if (!(!$.hasClass(quotelink, 'deadlink'))) { - continue; - } - $.add(quotelink, Post.deadMark.cloneNode(true)); - $.addClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.resurrect = function() { - var clone, j, k, len, len1, quotelink, ref, ref1, strong; - this.isDead = false; - $.rmClass(this.nodes.root, 'deleted-post'); - strong = $('strong.warning', this.nodes.info); - if (this.files.some(function(file) { - return file.isDead; - })) { - $.addClass(this.nodes.root, 'deleted-file'); - strong.textContent = '[File deleted]'; - } else { - $.rm(strong); - } - if (this.isClone) { - return; - } - ref = this.clones; - for (j = 0, len = ref.length; j < len; j++) { - clone = ref[j]; - clone.resurrect(); - } - ref1 = Get.allQuotelinksLinkingTo(this); - for (k = 0, len1 = ref1.length; k < len1; k++) { - quotelink = ref1[k]; - if (!($.hasClass(quotelink, 'deadlink'))) { - continue; - } - $.rm($('.qmark-dead', quotelink)); - $.rmClass(quotelink, 'deadlink'); - } - }; - - Post.prototype.collect = function() { - g.posts.rm(this.fullID); - this.thread.posts.rm(this); - return this.board.posts.rm(this); - }; - - Post.prototype.addClone = function(context, contractThumb) { - Callbacks.Post.execute(this); - return new Post.Clone(this, context, contractThumb); - }; - - Post.prototype.rmClone = function(index) { - var clone, j, len, ref; - this.clones.splice(index, 1); - ref = this.clones.slice(index); - for (j = 0, len = ref.length; j < len; j++) { - clone = ref[j]; - clone.nodes.root.dataset.clone = index++; - } - }; - - Post.prototype.setCatalogOP = function(isCatalogOP) { - this.nodes.root.classList.toggle('catalog-container', isCatalogOP); - this.nodes.root.classList.toggle('opContainer', !isCatalogOP); - this.nodes.post.classList.toggle('catalog-post', isCatalogOP); - this.nodes.post.classList.toggle('op', !isCatalogOP); - return this.nodes.post.style.left = this.nodes.post.style.right = null; - }; - - return Post; - - })(); - - return Post; - -}).call(this); - -(function() { - var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, - hasProp = {}.hasOwnProperty, - slice = [].slice; - - Post.Clone = (function(superClass) { - extend(_Class, superClass); - - _Class.prototype.isClone = true; - - function _Class() { - var that; - that = Object.create(Post.Clone.prototype); - that.construct.apply(that, arguments); - return that; - } - - _Class.prototype.construct = function(origin, context, contractThumb) { - var base, file, fileRoot, fileRoots, i, inline, inlined, j, k, key, l, len, len1, len2, len3, len4, m, node, nodes, originFile, ref, ref1, ref2, ref3, ref4, ref5, ref6, root, selector, val; - this.origin = origin; - this.context = context; - ref = ['ID', 'postID', 'threadID', 'boardID', 'siteID', 'fullID', 'board', 'thread', 'info', 'quotes', 'isReply']; - for (i = 0, len = ref.length; i < len; i++) { - key = ref[i]; - this[key] = this.origin[key]; - } - nodes = this.origin.nodes; - root = contractThumb ? this.cloneWithoutVideo(nodes.root) : nodes.root.cloneNode(true); - (base = Post.Clone).suffix || (base.suffix = 0); - ref1 = [root].concat(slice.call($$('[id]', root))); - for (j = 0, len1 = ref1.length; j < len1; j++) { - node = ref1[j]; - node.id += "_" + Post.Clone.suffix; - } - Post.Clone.suffix++; - ref2 = $$('.inline', root); - for (k = 0, len2 = ref2.length; k < len2; k++) { - inline = ref2[k]; - $.rm(inline); - } - ref3 = $$('.inlined', root); - for (l = 0, len3 = ref3.length; l < len3; l++) { - inlined = ref3[l]; - $.rmClass(inlined, 'inlined'); - } - this.nodes = this.parseNodes(root); - root.hidden = false; - $.rmClass(root, 'forwarded'); - $.rmClass(this.nodes.post, 'highlight'); - if (!this.isReply) { - this.setCatalogOP(false); - $.rm($('.catalog-link', this.nodes.post)); - $.rm($('.catalog-stats', this.nodes.post)); - $.rm($('.catalog-replies', this.nodes.post)); - } - this.parseQuotes(); - this.quotes = slice.call(this.origin.quotes); - this.files = []; - if (this.origin.files.length) { - fileRoots = this.fileRoots(); - } - ref4 = this.origin.files; - for (m = 0, len4 = ref4.length; m < len4; m++) { - originFile = ref4[m]; - file = {}; - for (key in originFile) { - val = originFile[key]; - file[key] = val; - } - fileRoot = fileRoots[file.docIndex]; - ref5 = g.SITE.selectors.file; - for (key in ref5) { - selector = ref5[key]; - file[key] = $(selector, fileRoot); - } - file.thumbLink = (ref6 = file.thumb) != null ? ref6.parentNode : void 0; - if (file.thumbLink) { - file.fullImage = $('.full-image', file.thumbLink); - } - file.videoControls = $('.video-controls', file.text); - if (file.videoThumb) { - file.thumb.muted = true; - } - this.files.push(file); - } - if (this.files.length) { - this.file = this.files[0]; - if (this.file.thumb && contractThumb) { - ImageExpand.contract(this); - } - } - if (this.origin.isDead) { - this.isDead = true; - } - return root.dataset.clone = this.origin.clones.push(this) - 1; - }; - - _Class.prototype.cloneWithoutVideo = function(node) { - var child, clone, i, len, ref; - if (node.tagName === 'VIDEO' && !node.dataset.md5) { - return []; - } else if (node.nodeType === Node.ELEMENT_NODE && $('video', node)) { - clone = node.cloneNode(false); - ref = node.childNodes; - for (i = 0, len = ref.length; i < len; i++) { - child = ref[i]; - $.add(clone, this.cloneWithoutVideo(child)); - } - return clone; - } else { - return node.cloneNode(true); - } - }; - - return _Class; - - })(Post); - -}).call(this); - -RandomAccessList = (function() { - var RandomAccessList; - - RandomAccessList = (function() { - function RandomAccessList(items) { - var i, item, len; - this.length = 0; - if (items) { - for (i = 0, len = items.length; i < len; i++) { - item = items[i]; - this.push(item); - } - } - } - - RandomAccessList.prototype.push = function(data) { - var ID, item, last; - ID = data.ID; - ID || (ID = data.id); - if (this[ID]) { - return; - } - last = this.last; - this[ID] = item = { - prev: last, - next: null, - data: data, - ID: ID - }; - item.prev = last; - this.last = last ? last.next = item : this.first = item; - return this.length++; - }; - - RandomAccessList.prototype.before = function(root, item) { - var prev; - if (item.next === root || item === root) { - return; - } - this.rmi(item); - prev = root.prev; - root.prev = item; - item.next = root; - item.prev = prev; - if (prev) { - return prev.next = item; - } else { - return this.first = item; - } - }; - - RandomAccessList.prototype.after = function(root, item) { - var next; - if (item.prev === root || item === root) { - return; - } - this.rmi(item); - next = root.next; - root.next = item; - item.prev = root; - item.next = next; - if (next) { - return next.prev = item; - } else { - return this.last = item; - } - }; - - RandomAccessList.prototype.prepend = function(item) { - var first; - first = this.first; - if (item === first || !this[item.ID]) { - return; - } - this.rmi(item); - item.next = first; - if (first) { - first.prev = item; - } else { - this.last = item; - } - this.first = item; - return delete item.prev; - }; - - RandomAccessList.prototype.shift = function() { - return this.rm(this.first.ID); - }; - - RandomAccessList.prototype.order = function() { - var item, order; - order = [item = this.first]; - while (item = item.next) { - order.push(item); - } - return order; - }; - - RandomAccessList.prototype.rm = function(ID) { - var item; - item = this[ID]; - if (!item) { - return; - } - delete this[ID]; - this.length--; - this.rmi(item); - delete item.next; - return delete item.prev; - }; - - RandomAccessList.prototype.rmi = function(item) { - var next, prev; - prev = item.prev, next = item.next; - if (prev) { - prev.next = next; - } else { - this.first = next; - } - if (next) { - return next.prev = prev; - } else { - return this.last = prev; - } - }; - - return RandomAccessList; - - })(); - - return RandomAccessList; - -}).call(this); - -ShimSet = (function() { - var ShimSet; - - ShimSet = (function() { - function ShimSet() { - this.elements = $.dict(); - this.size = 0; - } - - ShimSet.prototype.has = function(value) { - return value in this.elements; - }; - - ShimSet.prototype.add = function(value) { - if (this.elements[value]) { - return; - } - this.elements[value] = true; - return this.size++; - }; - - ShimSet.prototype["delete"] = function(value) { - if (!this.elements[value]) { - return; - } - delete this.elements[value]; - return this.size--; - }; - - return ShimSet; - - })(); - - if (!('Set' in window)) { - window.Set = ShimSet; - } - - return ShimSet; - -}).call(this); - -SimpleDict = (function() { - var SimpleDict, - slice = [].slice; - - SimpleDict = (function() { - function SimpleDict() { - this.keys = []; - } - - SimpleDict.prototype.push = function(key, data) { - key = "" + key; - if (!this[key]) { - this.keys.push(key); - } - return this[key] = data; - }; - - SimpleDict.prototype.rm = function(key) { - var i; - key = "" + key; - if ((i = this.keys.indexOf(key)) !== -1) { - this.keys.splice(i, 1); - return delete this[key]; - } - }; - - SimpleDict.prototype.forEach = function(fn) { - var j, key, len, ref; - ref = slice.call(this.keys); - for (j = 0, len = ref.length; j < len; j++) { - key = ref[j]; - fn(this[key]); - } - }; - - SimpleDict.prototype.get = function(key) { - if (key === 'keys') { - return void 0; - } else { - return $.getOwn(this, key); - } - }; - - return SimpleDict; - - })(); - - return SimpleDict; - -}).call(this); - -Thread = (function() { - var Thread; - - Thread = (function() { - Thread.prototype.toString = function() { - return this.ID; - }; - - function Thread(ID, board) { - this.board = board; - this.ID = +ID; - this.threadID = this.ID; - this.boardID = this.board.ID; - this.siteID = g.SITE.ID; - this.fullID = this.board + "." + this.ID; - this.posts = new SimpleDict(); - this.isDead = false; - this.isHidden = false; - this.isSticky = false; - this.isClosed = false; - this.isArchived = false; - this.postLimit = false; - this.fileLimit = false; - this.lastPost = 0; - this.ipCount = void 0; - this.json = null; - this.OP = null; - this.catalogView = null; - this.nodes = { - root: null - }; - this.board.threads.push(this.ID, this); - g.threads.push(this.fullID, this); - } - - Thread.prototype.setPage = function(pageNum) { - var icon, info, ref, reply; - ref = this.OP.nodes, info = ref.info, reply = ref.reply; - if (!(icon = $('.page-num', info))) { - icon = $.el('span', { - className: 'page-num' - }); - $.replace(reply.parentNode.previousSibling, [$.tn(' '), icon, $.tn(' ')]); - } - icon.title = "This thread is on page " + pageNum + " in the original index."; - icon.textContent = "[" + pageNum + "]"; - if (this.catalogView) { - return this.catalogView.nodes.pageCount.textContent = pageNum; - } - }; - - Thread.prototype.setCount = function(type, count, reachedLimit) { - var el; - if (!this.catalogView) { - return; - } - el = this.catalogView.nodes[type + "Count"]; - el.textContent = count; - return (reachedLimit ? $.addClass : $.rmClass)(el, 'warning'); - }; - - Thread.prototype.setStatus = function(type, status) { - var name; - name = "is" + type; - if (this[name] === status) { - return; - } - this[name] = status; - if (!this.OP) { - return; - } - this.setIcon('Sticky', this.isSticky); - this.setIcon('Closed', this.isClosed && !this.isArchived); - return this.setIcon('Archived', this.isArchived); - }; - - Thread.prototype.setIcon = function(type, status) { - var icon, root, typeLC; - typeLC = type.toLowerCase(); - icon = $("." + typeLC + "Icon", this.OP.nodes.info); - if (!!icon === status) { - return; - } - if (!status) { - $.rm(icon.previousSibling); - $.rm(icon); - if (this.catalogView) { - $.rm($("." + typeLC + "Icon", this.catalogView.nodes.icons)); - } - return; - } - icon = $.el('img', { - src: "" + g.SITE.Build.staticPath + typeLC + g.SITE.Build.gifIcon, - alt: type, - title: type, - className: typeLC + "Icon retina" - }); - if (g.BOARD.ID === 'f') { - icon.style.cssText = 'height: 18px; width: 18px;'; - } - root = type !== 'Sticky' && this.isSticky ? $('.stickyIcon', this.OP.nodes.info) : $('.page-num', this.OP.nodes.info) || this.OP.nodes.quote; - $.after(root, [$.tn(' '), icon]); - if (!this.catalogView) { - return; - } - return (type === 'Sticky' && this.isClosed ? $.prepend : $.add)(this.catalogView.nodes.icons, icon.cloneNode()); - }; - - Thread.prototype.kill = function() { - return this.isDead = true; - }; - - Thread.prototype.collect = function() { - var n; - n = 0; - this.posts.forEach(function(post) { - if (post.clones.length) { - return n++; - } else { - return post.collect(); - } - }); - if (!n) { - g.threads.rm(this.fullID); - return this.board.threads.rm(this); - } - }; - - return Thread; - - })(); - - return Thread; - -}).call(this); - -SW = {}; - -(function() { - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - SW.tinyboard = { - isOPContainerThread: true, - mayLackJSON: true, - threadModTimeIgnoresSage: true, - disabledFeatures: ['Resurrect Quotes', 'Quick Reply Personas', 'Quick Reply', 'Cooldown', 'Report Link', 'Delete Link', 'Edit Link', 'Quote Inlining', 'Quote Previewing', 'Quote Backlinks', 'File Info Formatting', 'Image Expansion', 'Image Expansion (Menu)', 'Comment Expansion', 'Thread Expansion', 'Favicon', 'Quote Threading', 'Thread Updater', 'Banner', 'Flash Features', 'Reply Pruning'], - detect: function() { - var j, len, m, properties, ref, root, script; - ref = $$('script:not([src])', d.head); - for (j = 0, len = ref.length; j < len; j++) { - script = ref[j]; - if ((m = script.textContent.match(/\bvar configRoot=(".*?")/))) { - properties = $.dict(); - try { - root = JSON.parse(m[1]); - if (root[0] === '/') { - properties.root = location.origin + root; - } else if (/^https?:/.test(root)) { - properties.root = root; - } - } catch (error) {} - return properties; - } - } - return false; - }, - awaitBoard: function(cb) { - var reactUI, s; - if ((reactUI = $.id('react-ui'))) { - s = this.selectors = Object.create(this.selectors); - s.boardFor = { - index: '.page-container' - }; - s.thread = 'div[id^="thread_"]'; - return Main.mounted(cb); - } else { - return cb(); - } - }, - urls: { - thread: function(arg, isArchived) { - var boardID, ref, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/" + (isArchived ? 'archive/' : '') + "res/" + threadID + ".html"; - }, - post: function(arg) { - var postID; - postID = arg.postID; - return "#" + postID; - }, - index: function(arg) { - var boardID, ref, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/"; - }, - catalog: function(arg) { - var boardID, ref, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/catalog.html"; - }, - threadJSON: function(arg, isArchived) { - var boardID, ref, root, siteID, threadID; - siteID = arg.siteID, boardID = arg.boardID, threadID = arg.threadID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/" + (isArchived ? 'archive/' : '') + "res/" + threadID + ".json"; - } else { - return ''; - } - }, - archivedThreadJSON: function(thread) { - return SW.tinyboard.urls.threadJSON(thread, true); - }, - threadsListJSON: function(arg) { - var boardID, ref, root, siteID; - siteID = arg.siteID, boardID = arg.boardID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/threads.json"; - } else { - return ''; - } - }, - archiveListJSON: function(arg) { - var boardID, ref, root, siteID; - siteID = arg.siteID, boardID = arg.boardID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/archive/archive.json"; - } else { - return ''; - } - }, - catalogJSON: function(arg) { - var boardID, ref, root, siteID; - siteID = arg.siteID, boardID = arg.boardID; - root = (ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0; - if (root) { - return "" + root + boardID + "/catalog.json"; - } else { - return ''; - } - }, - file: function(arg, filename) { - var boardID, ref, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return "" + (((ref = Conf['siteProperties'][siteID]) != null ? ref.root : void 0) || ("http://" + siteID + "/")) + boardID + "/" + filename; - }, - thumb: function(board, filename) { - return SW.tinyboard.urls.file(board, filename); - } - }, - selectors: { - board: 'form[name="postcontrols"]', - thread: 'input[name="board"] ~ div[id^="thread_"]', - threadDivider: 'div[id^="thread_"] > hr:last-child', - summary: '.omitted', - postContainer: 'div[id^="reply_"]:not(.hidden)', - opBottom: '.op', - replyOriginal: 'div[id^="reply_"]:not(.hidden)', - infoRoot: '.intro', - info: { - subject: '.subject', - name: '.name', - email: '.email', - tripcode: '.trip', - uniqueID: '.poster_id', - capcode: '.capcode', - flag: '.flag', - date: 'time', - nameBlock: 'label', - quote: 'a[href*="#q"]', - reply: 'a[href*="/res/"]:not([href*="#"])' - }, - icons: { - isSticky: '.fa-thumb-tack', - isClosed: '.fa-lock' - }, - file: { - text: '.fileinfo', - link: '.fileinfo > a', - thumb: 'a > .post-image' - }, - thumbLink: '.file > a', - multifile: '.files > .file', - highlightable: { - op: ' > .op', - reply: '.reply', - catalog: ' > .thread' - }, - comment: '.body', - spoiler: '.spoiler', - quotelink: 'a[onclick*="highlightReply("]', - catalog: { - board: '#Grid', - thread: '.mix', - thumb: '.thread-image' - }, - boardList: '.boardlist', - boardListBottom: '.boardlist.bottom', - styleSheet: '#stylesheet', - psa: '.blotter', - nav: { - prev: '.pages > form > [value=Previous]', - next: '.pages > form > [value=Next]' - } - }, - classes: { - highlight: 'highlighted' - }, - xpath: { - thread: 'div[starts-with(@id,"thread_")]', - postContainer: 'div[starts-with(@id,"reply_") or starts-with(@id,"thread_")]', - replyContainer: 'div[starts-with(@id,"reply_")]' - }, - regexp: { - quotelink: /\/([^\/]+)\/res\/(\d+)(?:\.\w+)?#(\d+)$/, - quotelinkHTML: /]*\bhref="[^"]*\/([^\/]+)\/res\/(\d+)(?:\.\w+)?#(\d+)"/g - }, - Build: { - parseJSON: function(data, board) { - var extra_file, file, i, j, len, o, ref; - o = SW.yotsuba.Build.parseJSON(data, board); - if (data.ext === 'deleted') { - delete o.file; - $.extend(o, { - files: [], - fileDeleted: true, - filesDeleted: [0] - }); - } - if (data.extra_files) { - ref = data.extra_files; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - extra_file = ref[i]; - if (extra_file.ext === 'deleted') { - o.filesDeleted.push(i); - } else { - file = SW.yotsuba.Build.parseJSONFile(data, board); - o.files.push(file); - } - } - if (o.files.length) { - o.file = o.files[0]; - } - } - return o; - }, - parseComment: function(html) { - html = html.replace(//gi, '\n').replace(/<[^>]*>/g, ''); - return $.unescape(html); - } - }, - bgColoredEl: function() { - return $.el('div', { - className: 'post reply' - }); - }, - isFileURL: function(url) { - return /\/src\/[^\/]+/.test(url.pathname); - }, - preParsingFixes: function(board) { - var broken; - if ((broken = $('a > input[name="board"]', board))) { - return $.before(broken.parentNode, broken); - } - }, - parseNodes: function(post, nodes) { - var m, nextSibling, node, text, uniqueID; - if (nodes.uniqueID) { - return; - } - text = ''; - node = nodes.nameBlock.nextSibling; - while (node && node.nodeType === 3) { - text += node.textContent; - node = node.nextSibling; - } - if ((m = text.match(/(\s*ID:\s*)(\S+)/))) { - nodes.info.normalize(); - nextSibling = nodes.nameBlock.nextSibling; - nextSibling = nextSibling.splitText(m[1].length); - nextSibling.splitText(m[2].length); - nodes.uniqueID = uniqueID = $.el('span', { - className: 'poster_id' - }); - $.replace(nextSibling, uniqueID); - return $.add(uniqueID, nextSibling); - } - }, - parseDate: function(node) { - var date, ref; - date = Date.parse((ref = node.getAttribute('datetime')) != null ? ref.trim() : void 0); - if (!isNaN(date)) { - return new Date(date); - } - date = Date.parse(node.textContent.trim() + ' UTC'); - if (!isNaN(date)) { - return new Date(date); - } - return void 0; - }, - parseFile: function(post, file) { - var info, infoNode, link, nameNode, ref, ref1, text, thumb; - text = file.text, link = file.link, thumb = file.thumb; - if ($.x("ancestor::" + this.xpath.postContainer + "[1]", text) !== post.nodes.root) { - return false; - } - if (!(infoNode = indexOf.call((ref = link.nextSibling) != null ? ref.textContent : void 0, '(') >= 0 ? link.nextSibling : link.nextElementSibling)) { - return false; - } - if (!(info = infoNode.textContent.match(/\((.*,\s*)?([\d.]+ ?[KMG]?B).*\)/))) { - return false; - } - nameNode = $('.postfilename', text); - $.extend(file, { - name: nameNode ? nameNode.title || nameNode.textContent : link.pathname.match(/[^\/]*$/)[0], - size: info[2], - dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0 - }); - if (thumb) { - $.extend(file, { - thumbURL: /\/static\//.test(thumb.src) && $.isImage(link.href) ? link.href : thumb.src, - isSpoiler: /^Spoiler/i.test(info[1] || '') || link.textContent === 'Spoiler Image' - }); - } - return true; - }, - isThumbExpanded: function(file) { - return $.hasClass(file.thumb.parentNode, 'expanded') || file.thumb.parentNode.dataset.expanded === 'true'; - }, - isLinkified: function(link) { - return /\bnofollow\b/.test(link.rel); - }, - catalogPin: function(threadRoot) { - return threadRoot.dataset.sticky = 'true'; - } - }; - -}).call(this); - -(function() { - var slice = [].slice; - - SW.yotsuba = { - isOPContainerThread: false, - hasIPCount: true, - archivedBoardsKnown: true, - urls: { - thread: function(arg) { - var boardID, threadID; - boardID = arg.boardID, threadID = arg.threadID; - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/thread/" + threadID; - }, - post: function(arg) { - var postID; - postID = arg.postID; - return "#p" + postID; - }, - index: function(arg) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/"; - }, - catalog: function(arg) { - var boardID; - boardID = arg.boardID; - if (boardID === 'f') { - return void 0; - } else { - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/catalog"; - } - }, - archive: function(arg) { - var boardID; - boardID = arg.boardID; - if (BoardConfig.isArchived(boardID)) { - return location.protocol + "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/archive"; - } else { - return void 0; - } - }, - threadJSON: function(arg) { - var boardID, threadID; - boardID = arg.boardID, threadID = arg.threadID; - return location.protocol + "//a.4cdn.org/" + boardID + "/thread/" + threadID + ".json"; - }, - threadsListJSON: function(arg) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//a.4cdn.org/" + boardID + "/threads.json"; - }, - archiveListJSON: function(arg) { - var boardID; - boardID = arg.boardID; - if (BoardConfig.isArchived(boardID)) { - return location.protocol + "//a.4cdn.org/" + boardID + "/archive.json"; - } else { - return ''; - } - }, - catalogJSON: function(arg) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//a.4cdn.org/" + boardID + "/catalog.json"; - }, - file: function(arg, filename) { - var boardID, hostname; - boardID = arg.boardID; - hostname = boardID === 'f' ? ImageHost.flashHost() : ImageHost.host(); - return location.protocol + "//" + hostname + "/" + boardID + "/" + filename; - }, - thumb: function(arg, filename) { - var boardID; - boardID = arg.boardID; - return location.protocol + "//" + (ImageHost.thumbHost()) + "/" + boardID + "/" + filename; - } - }, - isPrunedByAge: function(arg) { - var boardID; - boardID = arg.boardID; - return boardID === 'f'; - }, - areMD5sDeferred: function(arg) { - var boardID; - boardID = arg.boardID; - return boardID === 'f'; - }, - isOnePage: function(arg) { - var boardID; - boardID = arg.boardID; - return boardID === 'f'; - }, - noAudio: function(arg) { - var boardID; - boardID = arg.boardID; - return BoardConfig.noAudio(boardID); - }, - selectors: { - board: '.board', - thread: '.thread', - threadDivider: '.board > hr', - summary: '.summary', - postContainer: '.postContainer', - replyOriginal: '.replyContainer:not([data-clone])', - sideArrows: 'div.sideArrows', - post: '.post', - infoRoot: '.postInfo', - info: { - subject: '.subject', - name: '.name', - email: '.useremail', - tripcode: '.postertrip', - uniqueIDRoot: '.posteruid', - uniqueID: '.posteruid > .hand', - capcode: '.capcode.hand', - pass: '.n-pu', - flag: '.flag, .bfl', - date: '.dateTime', - nameBlock: '.nameBlock', - quote: '.postNum > a:nth-of-type(2)', - reply: '.replylink' - }, - icons: { - isSticky: '.stickyIcon', - isClosed: '.closedIcon', - isArchived: '.archivedIcon' - }, - file: { - text: '.file > :first-child', - link: '.fileText > a', - thumb: 'a.fileThumb > [data-md5]' - }, - thumbLink: 'a.fileThumb', - highlightable: { - op: '.opContainer', - reply: ' > .reply', - catalog: '' - }, - comment: '.postMessage', - spoiler: 's', - quotelink: ':not(pre) > .quotelink', - catalog: { - board: '#threads', - thread: '.thread', - thumb: '.thumb' - }, - boardList: '#boardNavDesktop > .boardList', - boardListBottom: '#boardNavDesktopFoot > .boardList', - styleSheet: 'link[title=switch]', - psa: '#globalMessage', - psaTop: '#globalToggle', - searchBox: '#search-box', - nav: { - prev: '.prev > form > [type=submit]', - next: '.next > form > [type=submit]' - } - }, - classes: { - highlight: 'highlight' - }, - xpath: { - thread: 'div[contains(concat(" ",@class," ")," thread ")]', - postContainer: 'div[contains(@class,"postContainer")]', - replyContainer: 'div[contains(@class,"replyContainer")]' - }, - regexp: { - quotelink: /^https?:\/\/boards\.4chan(?:nel)?\.org\/+([^\/]+)\/+thread\/+(\d+)(?:[\/?][^#]*)?(?:#p(\d+))?$/, - quotelinkHTML: /]*\bhref="(?:(?:\/\/boards\.4chan(?:nel)?\.org)?\/([^\/]+)\/thread\/)?(\d+)?(?:#p(\d+))?"/g, - pass: /^https?:\/\/www\.4chan(?:nel)?\.org\/+pass(?:$|[?#])/, - captcha: /^https?:\/\/sys\.4chan(?:nel)?\.org\/+captcha(?:$|[?#])/ - }, - bgColoredEl: function() { - return $.el('div', { - className: 'reply' - }); - }, - isThisPageLegit: function() { - var ref, ref1; - return ((ref = location.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') && d.doctype && !$('link[href*="favicon-status.ico"]', d.head) && ((ref1 = d.title) !== '4chan - Temporarily Offline' && ref1 !== '4chan - Error' && ref1 !== '504 Gateway Time-out' && ref1 !== 'MathJax Equation Source'); - }, - is404: function() { - var ref; - return ((ref = d.title) === '4chan - Temporarily Offline' || ref === '4chan - 404 Not Found') || (g.VIEW === 'thread' && $('.board') && !$('.opContainer')); - }, - isIncomplete: function() { - var ref; - return ((ref = g.VIEW) === 'index' || ref === 'thread') && !$('.board + *'); - }, - isBoardlessPage: function(url) { - var ref; - return (ref = url.hostname) === 'www.4chan.org' || ref === 'www.4channel.org'; - }, - isAuxiliaryPage: function(url) { - var ref; - return (ref = url.hostname) !== 'boards.4chan.org' && ref !== 'boards.4channel.org'; - }, - isFileURL: function(url) { - return ImageHost.test(url.hostname); - }, - initAuxiliary: function() { - var match, pathname; - switch (location.hostname) { - case 'www.4chan.org': - case 'www.4channel.org': - if (SW.yotsuba.regexp.pass.test(location.href)) { - PassMessage.init(); - } else { - $.onExists(doc, 'body', function() { - return $.addStyle(CSS.www); - }); - Captcha.replace.init(); - } - break; - case 'sys.4chan.org': - case 'sys.4channel.org': - pathname = location.pathname.split(/\/+/); - if (pathname[2] === 'imgboard.php') { - if (/\bmode=report\b/.test(location.search)) { - Report.init(); - } else if ((match = location.search.match(/\bres=(\d+)/))) { - $.ready(function() { - var ref; - if (Conf['404 Redirect'] && ((ref = $.id('errmsg')) != null ? ref.textContent : void 0) === 'Error: Specified thread does not exist.') { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - postID: +match[1] - }); - } - }); - } - } else if (pathname[2] === 'post') { - PostSuccessful.init(); - } - } - }, - scriptData: function() { - var j, len, ref, script; - ref = $$('script:not([src])', d.head); - for (j = 0, len = ref.length; j < len; j++) { - script = ref[j]; - if (/\bcooldowns *=/.test(script.textContent)) { - return script.textContent; - } - } - return ''; - }, - parseThreadMetadata: function(thread) { - var file, m, scriptData; - scriptData = this.scriptData(); - thread.postLimit = /\bbumplimit *= *1\b/.test(scriptData); - thread.fileLimit = /\bimagelimit *= *1\b/.test(scriptData); - thread.ipCount = (m = scriptData.match(/\bunique_ips *= *(\d+)\b/)) ? +m[1] : void 0; - if (g.BOARD.ID === 'f' && thread.OP.file) { - file = thread.OP.file; - return $.ajax(this.urls.threadJSON({ - boardID: 'f', - threadID: thread.ID - }), { - timeout: $.MINUTE, - onloadend: function() { - if (this.response) { - return file.text.dataset.md5 = file.MD5 = this.response.posts[0].md5; - } - } - }); - } - }, - parseNodes: function(post, nodes) { - var icon, j, len, ref, results, type; - if (post.boardID === 'f') { - ref = ['Sticky', 'Closed']; - results = []; - for (j = 0, len = ref.length; j < len; j++) { - type = ref[j]; - if ((icon = $("img[alt=" + type + "]", nodes.info))) { - results.push($.addClass(icon, (type.toLowerCase()) + "Icon", 'retina')); - } - } - return results; - } - }, - parseDate: function(node) { - return new Date(node.dataset.utc * 1000); - }, - parseFile: function(post, file) { - var info, link, m, ref, ref1, ref2, text, thumb; - text = file.text, link = file.link, thumb = file.thumb; - if (!(info = (ref = link.nextSibling) != null ? ref.textContent.match(/\(([\d.]+ [KMG]?B).*\)/) : void 0)) { - return false; - } - $.extend(file, { - name: text.title || link.title || link.textContent, - size: info[1], - dimensions: (ref1 = info[0].match(/\d+x\d+/)) != null ? ref1[0] : void 0, - tag: (ref2 = info[0].match(/,[^,]*, ([a-z]+)\)/i)) != null ? ref2[1] : void 0, - MD5: text.dataset.md5 - }); - if (thumb) { - $.extend(file, { - thumbURL: thumb.src, - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(thumb.parentNode, 'imgspoiler') - }); - if (file.isSpoiler) { - file.thumbURL = (m = link.href.match(/\d+(?=\.\w+$)/)) ? location.protocol + "//" + (ImageHost.thumbHost()) + "/" + post.board + "/" + m[0] + "s.jpg" : void 0; - } - } - return true; - }, - cleanComment: function(bq) { - var abbr, br, i, j, k, len, node, ref; - if ((abbr = $('.abbr', bq))) { - ref = $$('.abbr + br, .exif', bq); - for (j = 0, len = ref.length; j < len; j++) { - node = ref[j]; - $.rm(node); - } - for (i = k = 0; k < 2; i = ++k) { - if ((br = abbr.previousSibling) && br.nodeName === 'BR') { - $.rm(br); - } - } - return $.rm(abbr); - } - }, - cleanCommentDisplay: function(bq) { - var b; - if ((b = $('b', bq)) && /^Rolled /.test(b.textContent)) { - $.rm(b); - } - return $.rm($('.fortune', bq)); - }, - insertTags: function(bq) { - var j, k, len, len1, node, ref, ref1; - ref = $$('s, .removed-spoiler', bq); - for (j = 0, len = ref.length; j < len; j++) { - node = ref[j]; - $.replace(node, [$.tn('[spoiler]')].concat(slice.call(node.childNodes), [$.tn('[/spoiler]')])); - } - ref1 = $$('.prettyprint', bq); - for (k = 0, len1 = ref1.length; k < len1; k++) { - node = ref1[k]; - $.replace(node, [$.tn('[code]')].concat(slice.call(node.childNodes), [$.tn('[/code]')])); - } - }, - hasCORS: function(url) { - return url.split('/').slice(0, 3).join('/') === location.protocol + '//a.4cdn.org'; - }, - sfwBoards: function(sfw) { - return BoardConfig.sfwBoards(sfw); - }, - uidColor: function(uid) { - var i, msg; - msg = 0; - i = 0; - while (i < 8) { - msg = (msg << 5) - msg + uid.charCodeAt(i++); - } - return (msg >> 8) & 0xFFFFFF; - }, - isLinkified: function(link) { - return ImageHost.test(link.hostname); - }, - testNativeExtension: function() { - return $.global(function() { - if (window.Parser.postMenuIcon) { - return this.enabled = 'true'; - } - }); - }, - transformBoardList: function() { - var a, chr, i, items, j, len, node, nodes, ref, spacer, span; - nodes = []; - spacer = function() { - return $.el('span', { - className: 'spacer' - }); - }; - items = $.X('.//a|.//text()[not(ancestor::a)]', $(SW.yotsuba.selectors.boardList)); - i = 0; - while (node = items.snapshotItem(i++)) { - switch (node.nodeName) { - case '#text': - ref = node.nodeValue; - for (j = 0, len = ref.length; j < len; j++) { - chr = ref[j]; - span = $.el('span', { - textContent: chr - }); - if (chr === ' ') { - span.className = 'space'; - } - if (chr === ']') { - nodes.push(spacer()); - } - nodes.push(span); - if (chr === '[') { - nodes.push(spacer()); - } - } - break; - case 'A': - a = node.cloneNode(true); - nodes.push(a); - } - } - return nodes; - } - }; - -}).call(this); - -(function() { - var Build, - slice = [].slice; - - Build = { - staticPath: '//s.4cdn.org/image/', - gifIcon: window.devicePixelRatio >= 2 ? '@2x.gif' : '.gif', - spoilerRange: $.dict(), - shortFilename: function(filename) { - var ext; - ext = filename.match(/\.?[^\.]*$/)[0]; - if (filename.length - ext.length > 30) { - return (filename.match(/(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[^]){0,25}/)[0]) + "(...)" + ext; - } else { - return filename; - } - }, - spoilerThumb: function(boardID) { - var spoilerRange; - if (spoilerRange = Build.spoilerRange[boardID]) { - return Build.staticPath + "spoiler-" + boardID + (Math.floor(1 + spoilerRange * Math.random())) + ".png"; - } else { - return Build.staticPath + "spoiler.png"; - } - }, - sameThread: function(boardID, threadID) { - return g.VIEW === 'thread' && g.BOARD.ID === boardID && g.THREADID === +threadID; - }, - threadURL: function(boardID, threadID) { - if (boardID !== g.BOARD.ID) { - return "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/thread/" + threadID; - } else if (g.VIEW !== 'thread' || +threadID !== g.THREADID) { - return "/" + boardID + "/thread/" + threadID; - } else { - return ''; - } - }, - postURL: function(boardID, threadID, postID) { - return (Build.threadURL(boardID, threadID)) + "#p" + postID; - }, - parseJSON: function(data, arg) { - var boardID, key, o, siteID; - siteID = arg.siteID, boardID = arg.boardID; - o = { - ID: data.no, - postID: data.no, - threadID: data.resto || data.no, - boardID: boardID, - siteID: siteID, - isReply: !!data.resto, - isSticky: !!data.sticky, - isClosed: !!data.closed, - isArchived: !!data.archived, - fileDeleted: !!data.filedeleted, - filesDeleted: data.filedeleted ? [0] : [] - }; - o.info = { - subject: $.unescape(data.sub), - email: $.unescape(data.email), - name: $.unescape(data.name) || '', - tripcode: data.trip, - pass: data.since4pass != null ? "" + data.since4pass : void 0, - uniqueID: data.id, - flagCode: data.country, - flagCodeTroll: data.board_flag, - flag: $.unescape(data.country_name || data.flag_name), - dateUTC: data.time, - dateText: data.now, - commentHTML: { - innerHTML: data.com || '' - } - }; - if (data.capcode) { - o.info.capcode = data.capcode.replace(/_highlight$/, '').replace(/_/g, ' ').replace(/\b\w/g, function(c) { - return c.toUpperCase(); - }); - o.capcodeHighlight = /_highlight$/.test(data.capcode); - delete o.info.uniqueID; - } - o.files = []; - if (data.ext) { - o.file = SW.yotsuba.Build.parseJSONFile(data, { - siteID: siteID, - boardID: boardID - }); - o.files.push(o.file); - } - o.extra = $.dict(); - for (key in data) { - if (key[0] === 'x') { - o.extra[key] = data[key]; - } - } - return o; - }, - parseJSONFile: function(data, arg) { - var boardID, filename, o, site, siteID; - siteID = arg.siteID, boardID = arg.boardID; - site = g.sites[siteID]; - filename = site.software === 'yotsuba' && boardID === 'f' ? "" + (encodeURIComponent(data.filename)) + data.ext : "" + data.tim + data.ext; - o = { - name: ($.unescape(data.filename)) + data.ext, - url: site.urls.file({ - siteID: siteID, - boardID: boardID - }, filename), - height: data.h, - width: data.w, - MD5: data.md5, - size: $.bytesToString(data.fsize), - thumbURL: site.urls.thumb({ - siteID: siteID, - boardID: boardID - }, data.tim + "s.jpg"), - theight: data.tn_h, - twidth: data.tn_w, - isSpoiler: !!data.spoiler, - tag: data.tag, - hasDownscale: !!data.m_img - }; - if ((data.h != null) && !/\.pdf$/.test(o.url)) { - o.dimensions = o.width + "x" + o.height; - } - return o; - }, - parseComment: function(html) { - html = html.replace(//gi, '\n').replace(/\n\n]*>/g, ''); - return $.unescape(html); - }, - parseCommentDisplay: function(html) { - var html2; - if (!(Conf['Remove Spoilers'] || Conf['Reveal Spoilers'])) { - while ((html2 = html.replace(/(?:(?!<\/?s>).)*<\/s>/g, '[spoiler]')) !== html) { - html = html2; - } - } - html = html.replace(/^Rolled [^<]*<\/b>/i, '').replace(/ " + ((!o.isReply || boardID === "f" || subject) ? "" + E(subject || "") + " " : "") + "" + ((email) ? "" : "") + "" + E(name) + "" + ((tripcode) ? " " + E(tripcode) + "" : "") + ((pass) ? " " : "") + ((capcode) ? " ## " + E(capcode) + "" : "") + ((email) ? "" : "") + ((boardID === "f" && !o.isReply || capcodeDescription) ? "" : " ") + ((capcodeDescription) ? " \""" : "") + ((uniqueID && !capcode) ? " (ID: " + E(uniqueID) + ")" : "") + ((flagCode) ? " " : "") + ((flagCodeTroll) ? " " : "") + "
    " + E(dateText) + " No." + E(ID) + "" + ((o.isSticky) ? " \"Sticky\"" : "") + ((o.isClosed && !o.isArchived) ? " \"Closed\"" : "") + ((o.isArchived) ? " \"Archived\"" : "") + ((!o.isReply && g.VIEW === "index") ? "   [Reply]" : "") + ""}; - - /* File Info */ - if (file) { - protocol = /^https?:(?=\/\/i\.4cdn\.org\/)/; - fileURL = file.url.replace(protocol, ''); - shortFilename = Build.shortFilename(file.name); - fileThumb = file.isSpoiler ? Build.spoilerThumb(boardID) : file.thumbURL.replace(protocol, ''); - } - fileBlock = {innerHTML: ((file) ? "
    " + ((boardID === "f") ? "
    File: " + E(file.name) + "-(" + E(file.size) + ", " + E(file.dimensions) + ((file.tag) ? ", " + E(file.tag) : "") + ")
    " : "
    File: " + ((file.isSpoiler) ? "Spoiler Image" : E(shortFilename)) + " (" + E(file.size) + ", " + E(file.dimensions || "PDF") + ")
    \""") + "
    " : ((o.fileDeleted) ? "
    \"File
    " : ""))}; - - /* Whole Post */ - postClass = o.isReply ? 'reply' : 'op'; - wholePost = {innerHTML: ((o.isReply) ? "
    >>
    " : "") + "
    " + ((o.isReply) ? (postInfo).innerHTML + (fileBlock).innerHTML : (fileBlock).innerHTML + (postInfo).innerHTML) + "
    " + (commentHTML).innerHTML + "
    "}; - container = $.el('div', { - className: "postContainer " + postClass + "Container", - id: "pc" + ID - }); - $.extend(container, wholePost); - ref1 = $$('.quotelink', container); - for (i = 0, len = ref1.length; i < len; i++) { - quote = ref1[i]; - href = quote.getAttribute('href'); - if (href[0] === '#') { - if (!Build.sameThread(boardID, threadID)) { - quote.href = Build.threadURL(boardID, threadID) + href; - } - } else { - if ((match = quote.href.match(SW.yotsuba.regexp.quotelink)) && (Build.sameThread(match[1], match[2]))) { - quote.href = href.match(/(#[^#]*)?$/)[0] || '#'; - } - } - } - return container; - }, - summaryText: function(status, posts, files) { - var text; - text = ''; - if (status) { - text += status + " "; - } - text += posts + " post" + (posts > 1 ? 's' : ''); - if (+files) { - text += " and " + files + " image repl" + (files > 1 ? 'ies' : 'y'); - } - return text += " " + (status === '-' ? 'shown' : 'omitted') + "."; - }, - summary: function(boardID, threadID, posts, files) { - return $.el('a', { - className: 'summary', - textContent: Build.summaryText('', posts, files), - href: "/" + boardID + "/thread/" + threadID - }); - }, - thread: function(thread, data, withReplies) { - var files, posts, ref, root, summary; - if ((root = thread.nodes.root)) { - $.rmAll(root); - } else { - thread.nodes.root = root = $.el('div', { - className: 'thread', - id: "t" + data.no - }); - } - if (Build.hat) { - $.add(root, Build.hat.cloneNode(false)); - } - $.add(root, thread.OP.nodes.root); - if (data.omitted_posts || !withReplies && data.replies) { - ref = withReplies ? [ - data.omitted_posts, data.images - data.last_replies.filter(function(data) { - return !!data.ext; - }).length - ] : [data.replies, data.images], posts = ref[0], files = ref[1]; - summary = Build.summary(thread.board.ID, data.no, posts, files); - $.add(root, summary); - } - return root; - }, - catalogThread: function(thread, data, pageCount) { - var br, container, cssText, fileCount, gifIcon, i, imgClass, len, postCount, ratio, ref, root, spoilerRange, src, staticPath, tn_h, tn_w; - staticPath = Build.staticPath, gifIcon = Build.gifIcon; - tn_w = data.tn_w, tn_h = data.tn_h; - if (data.spoiler && !Conf['Reveal Spoiler Thumbnails']) { - src = staticPath + "spoiler"; - if (spoilerRange = Build.spoilerRange[thread.board]) { - src += ("-" + thread.board) + Math.floor(1 + spoilerRange * Math.random()); - } - src += '.png'; - imgClass = 'spoiler-file'; - cssText = "--tn-w: 100; --tn-h: 100;"; - } else if (data.filedeleted) { - src = staticPath + "filedeleted-res" + gifIcon; - imgClass = 'deleted-file'; - } else if (thread.OP.file) { - src = thread.OP.file.thumbURL; - ratio = 250 / Math.max(tn_w, tn_h); - cssText = "--tn-w: " + (tn_w * ratio) + "; --tn-h: " + (tn_h * ratio) + ";"; - } else { - src = staticPath + "nofile.png"; - imgClass = 'no-file'; - } - postCount = data.replies + 1; - fileCount = data.images + !!data.ext; - container = $.el('div', {innerHTML: "
    " + E(postCount) + " / " + E(fileCount) + " / " + E(pageCount) + "" + ((thread.isSticky) ? "" : "") + ((thread.isClosed) ? "" : "") + "
    "}); - $.before(thread.OP.nodes.info, slice.call(container.childNodes)); - ref = $$('br', thread.OP.nodes.comment); - for (i = 0, len = ref.length; i < len; i++) { - br = ref[i]; - if (br.previousSibling && br.previousSibling.nodeName === 'BR') { - $.addClass(br, 'extra-linebreak'); - } - } - root = $.el('div', { - className: 'thread catalog-thread', - id: "t" + thread - }); - if (thread.OP.highlights) { - $.addClass.apply($, [root].concat(slice.call(thread.OP.highlights))); - } - if (!thread.OP.file) { - $.addClass(root, 'noFile'); - } - root.style.cssText = cssText || ''; - return root; - }, - catalogReply: function(thread, data) { - var excerpt, link; - excerpt = ''; - if (data.com) { - excerpt = Build.parseCommentDisplay(data.com).replace(/>>\d+/g, '').trim().replace(/\n+/g, ' // '); - } - if (data.ext) { - excerpt || (excerpt = "" + ($.unescape(data.filename)) + data.ext); - } - if (data.com) { - excerpt || (excerpt = $.unescape(data.com.replace(//gi, ' // '))); - } - excerpt || (excerpt = '\xA0'); - if (excerpt.length > 73) { - excerpt = excerpt.slice(0, 70) + "..."; - } - link = Build.postURL(thread.board.ID, thread.ID, data.no); - return $.el('div', { - className: 'catalog-reply' - }, {innerHTML: ": " + E(excerpt) + "..."}); - } - }; - - SW.yotsuba.Build = Build; - -}).call(this); - -Site = (function() { - var Site; - - Site = { - defaultProperties: { - '4chan.org': { - software: 'yotsuba' - }, - '4channel.org': { - canonical: '4chan.org' - }, - '4cdn.org': { - canonical: '4chan.org' - }, - 'notso.smuglo.li': { - canonical: 'smuglo.li' - }, - 'smugloli.net': { - canonical: 'smuglo.li' - }, - 'smug.nepu.moe': { - canonical: 'smuglo.li' - } - }, - init: function(cb) { - var hostname; - $.extend(Conf['siteProperties'], Site.defaultProperties); - hostname = Site.resolve(); - if (hostname && $.hasOwn(SW, Conf['siteProperties'][hostname].software)) { - this.set(hostname); - cb(); - } - return $.onExists(doc, 'body', (function(_this) { - return function() { - var base, base1, changed, changes, key, properties, software; - for (software in SW) { - if (!((changes = typeof (base = SW[software]).detect === "function" ? base.detect() : void 0))) { - continue; - } - changes.software = software; - hostname = location.hostname.replace(/^www\./, ''); - properties = ((base1 = Conf['siteProperties'])[hostname] || (base1[hostname] = $.dict())); - changed = 0; - for (key in changes) { - if (!(properties[key] !== changes[key])) { - continue; - } - properties[key] = changes[key]; - changed++; - } - if (changed) { - $.set('siteProperties', Conf['siteProperties']); - } - if (!g.SITE) { - _this.set(hostname); - cb(); - } - return; - } - }; - })(this)); - }, - resolve: function(url) { - var canonical, hostname; - if (url == null) { - url = location; - } - hostname = url.hostname; - while (hostname && !$.hasOwn(Conf['siteProperties'], hostname)) { - hostname = hostname.replace(/^[^.]*\.?/, ''); - } - if (hostname) { - if ((canonical = Conf['siteProperties'][hostname].canonical)) { - hostname = canonical; - } - } - return hostname; - }, - parseURL: function(url) { - var siteID; - siteID = Site.resolve(url); - return Main.parseURL(g.sites[siteID], url); - }, - set: function(hostname) { - var ID, properties, ref, site, software; - ref = Conf['siteProperties']; - for (ID in ref) { - properties = ref[ID]; - if (properties.canonical) { - continue; - } - software = properties.software; - if (!(software && $.hasOwn(SW, software))) { - continue; - } - g.sites[ID] = site = Object.create(SW[software]); - $.extend(site, { - ID: ID, - siteID: ID, - properties: properties, - software: software - }); - } - return g.SITE = g.sites[hostname]; - } - }; - - return Site; - -}).call(this); - -Redirect = (function() { - var Redirect, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Redirect = { - archives: [ - { "uid": 3, "name": "4plebs", "domain": "archive.4plebs.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "adv", "f", "hr", "mlpol", "mo", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ], "files": [ "adv", "f", "hr", "mlpol", "mo", "o", "pol", "s4s", "sp", "tg", "trv", "tv", "x" ], "reports": true }, - { "uid": 10, "name": "warosu", "domain": "warosu.org", "http": false, "https": true, "software": "fuuka", "boards": [ "3", "biz", "cgl", "ck", "diy", "fa", "ic", "jp", "lit", "sci", "vr", "vt" ], "files": [ "3", "biz", "cgl", "ck", "diy", "fa", "ic", "jp", "lit", "sci", "vr", "vt" ], "search": [ "biz", "cgl", "ck", "diy", "fa", "ic", "jp", "lit", "sci", "vr", "vt" ] }, - { "uid": 23, "name": "Desuarchive", "domain": "desuarchive.org", "http": true, "https": true, "software": "foolfuuka", "boards": [ "a", "aco", "an", "c", "cgl", "co", "d", "fit", "g", "his", "int", "k", "m", "mlp", "mu", "q", "qa", "r9k", "tg", "trash", "vr", "wsg" ], "files": [ "a", "aco", "an", "c", "cgl", "co", "d", "fit", "g", "his", "int", "k", "m", "mlp", "mu", "q", "qa", "r9k", "tg", "trash", "vr" ], "reports": true }, - { "uid": 24, "name": "fireden.net", "domain": "boards.fireden.net", "http": false, "https": true, "software": "foolfuuka", "boards": [ "cm", "co", "ic", "sci", "vip", "y" ], "files": [ "cm", "co", "ic", "sci", "vip", "y" ], "search": [ "cm", "co", "ic", "sci", "y" ] }, - { "uid": 25, "name": "arch.b4k.co", "domain": "arch.b4k.co", "http": true, "https": true, "software": "foolfuuka", "boards": [ "g", "mlp", "qb", "v", "vg", "vm", "vmg", "vp", "vrpg", "vst" ], "files": [ "qb", "v", "vg", "vm", "vmg", "vp", "vrpg", "vst" ], "search": [ "qb", "v", "vg", "vm", "vmg", "vp", "vrpg", "vst" ] }, - { "uid": 29, "name": "Archived.Moe", "domain": "archived.moe", "http": true, "https": true, "software": "foolfuuka", "boards": [ "3", "a", "aco", "adv", "an", "asp", "b", "bant", "biz", "c", "can", "cgl", "ck", "cm", "co", "cock", "con", "d", "diy", "e", "f", "fa", "fap", "fit", "fitlit", "g", "gd", "gif", "h", "hc", "his", "hm", "hr", "i", "ic", "int", "jp", "k", "lgbt", "lit", "m", "mlp", "mlpol", "mo", "mtv", "mu", "n", "news", "o", "out", "outsoc", "p", "po", "pol", "pw", "q", "qa", "qb", "qst", "r", "r9k", "s", "s4s", "sci", "soc", "sp", "spa", "t", "tg", "toy", "trash", "trv", "tv", "u", "v", "vg", "vint", "vip", "vm", "vmg", "vp", "vr", "vrpg", "vst", "vt", "w", "wg", "wsg", "wsr", "x", "xs", "y" ], "files": [ "can", "cock", "con", "fap", "fitlit", "gd", "mlpol", "mo", "mtv", "outsoc", "po", "q", "qb", "qst", "spa", "vint", "vip" ], "search": [ "aco", "adv", "an", "asp", "b", "bant", "biz", "c", "can", "cgl", "ck", "cm", "cock", "con", "d", "diy", "e", "f", "fap", "fitlit", "gd", "gif", "h", "hc", "his", "hm", "hr", "i", "ic", "lgbt", "lit", "mlpol", "mo", "mtv", "n", "news", "o", "out", "outsoc", "p", "po", "pw", "q", "qa", "qst", "r", "s", "soc", "spa", "trv", "u", "vint", "vip", "vrpg", "w", "wg", "wsg", "wsr", "x", "y" ], "reports": true }, - { "uid": 30, "name": "TheBArchive.com", "domain": "thebarchive.com", "http": true, "https": true, "software": "foolfuuka", "boards": [ "b", "bant" ], "files": [ "b", "bant" ], "reports": true }, - { "uid": 31, "name": "Archive Of Sins", "domain": "archiveofsins.com", "http": true, "https": true, "software": "foolfuuka", "boards": [ "h", "hc", "hm", "i", "lgbt", "r", "s", "soc", "t", "u" ], "files": [ "h", "hc", "hm", "i", "lgbt", "r", "s", "soc", "t", "u" ], "reports": true }, - { "uid": 34, "name": "TokyoChronos", "domain": "www.tokyochronos.net", "http": false, "https": true, "software": "foolfuuka", "boards": [ "c", "g", "jp", "mu", "vp", "vrpg", "vt" ], "files": [], "reports": true }, - { "uid": 36, "name": "palanq.win", "domain": "archive.palanq.win", "http": false, "https": true, "software": "foolfuuka", "boards": [ "bant", "c", "con", "e", "i", "n", "news", "out", "p", "pw", "qst", "toy", "vip", "vp", "vt", "w", "wg", "wsr" ], "files": [ "bant", "c", "e", "i", "n", "news", "out", "p", "pw", "qst", "toy", "vip", "vp", "vt", "w", "wg", "wsr" ], "reports": true }, - { "uid": 37, "name": "Eientei", "domain": "eientei.xyz", "http": false, "https": true, "software": "Eientei", "boards": [ "3", "i", "sci", "xs" ], "files": [ "3", "i", "sci", "xs" ], "reports": true } - ], - init: function() { - var now, ref; - this.selectArchives(); - if (Conf['archiveAutoUpdate']) { - now = Date.now(); - if (!((now - 2 * $.DAY < (ref = Conf['lastarchivecheck']) && ref <= now))) { - return this.update(); - } - } - }, - selectArchives: function() { - var archive, archives, boardID, boards, data, files, id, j, k, key, l, len, len1, len2, name, o, record, ref, ref1, ref2, software, type, uid; - o = { - thread: $.dict(), - post: $.dict(), - file: $.dict() - }; - archives = $.dict(); - ref = Conf['archives']; - for (j = 0, len = ref.length; j < len; j++) { - data = ref[j]; - ref1 = ['boards', 'files']; - for (k = 0, len1 = ref1.length; k < len1; k++) { - key = ref1[k]; - if (!(data[key] instanceof Array)) { - data[key] = []; - } - } - uid = data.uid, name = data.name, boards = data.boards, files = data.files, software = data.software; - if (software !== 'fuuka' && software !== 'foolfuuka') { - continue; - } - archives[JSON.stringify(uid != null ? uid : name)] = data; - for (l = 0, len2 = boards.length; l < len2; l++) { - boardID = boards[l]; - if (!(boardID in o.thread)) { - o.thread[boardID] = data; - } - if (!(boardID in o.post || software !== 'foolfuuka')) { - o.post[boardID] = data; - } - if (!(boardID in o.file || indexOf.call(files, boardID) < 0)) { - o.file[boardID] = data; - } - } - } - ref2 = Conf['selectedArchives']; - for (boardID in ref2) { - record = ref2[boardID]; - for (type in record) { - id = record[type]; - if (!((archive = archives[JSON.stringify(id)]) && $.hasOwn(o, type))) { - continue; - } - boards = type === 'file' ? archive.files : archive.boards; - if (indexOf.call(boards, boardID) >= 0) { - o[type][boardID] = archive; - } - } - } - return Redirect.data = o; - }, - update: function(cb) { - var err, fail, i, j, k, len, len1, load, nloaded, ref, ref1, response, responses, url, urls; - urls = []; - responses = []; - nloaded = 0; - ref = Conf['archiveLists'].split('\n'); - for (j = 0, len = ref.length; j < len; j++) { - url = ref[j]; - if (!(url[0] !== '#')) { - continue; - } - url = url.trim(); - if (url) { - urls.push(url); - } - } - fail = function(url, action, msg) { - return new Notice('warning', "Error " + action + " archive data from\n" + url + "\n" + msg, 20); - }; - load = function(i) { - return function() { - var response; - if (this.status !== 200) { - return fail(urls[i], 'fetching', (this.status ? "Error " + this.statusText + " (" + this.status + ")" : 'Connection Error')); - } - response = this.response; - if (!(response instanceof Array)) { - response = [response]; - } - responses[i] = response; - nloaded++; - if (nloaded === urls.length) { - return Redirect.parse(responses, cb); - } - }; - }; - if (urls.length) { - for (i = k = 0, len1 = urls.length; k < len1; i = ++k) { - url = urls[i]; - if ((ref1 = url[0]) === '[' || ref1 === '{') { - try { - response = JSON.parse(url); - } catch (error) { - err = error; - fail(url, 'parsing', err.message); - continue; - } - load(i).call({ - status: 200, - response: response - }); - } else { - CrossOrigin.ajax(url, { - onloadend: load(i) - }); - } - } - } else { - Redirect.parse([], cb); - } - }, - parse: function(responses, cb) { - var archiveUIDs, archives, data, items, j, k, len, len1, ref, response, uid; - archives = []; - archiveUIDs = $.dict(); - for (j = 0, len = responses.length; j < len; j++) { - response = responses[j]; - for (k = 0, len1 = response.length; k < len1; k++) { - data = response[k]; - uid = JSON.stringify((ref = data.uid) != null ? ref : data.name); - if (uid in archiveUIDs) { - $.extend(archiveUIDs[uid], data); - } else { - archiveUIDs[uid] = $.dict.clone(data); - archives.push(data); - } - } - } - items = { - archives: archives, - lastarchivecheck: Date.now() - }; - $.set(items); - $.extend(Conf, items); - Redirect.selectArchives(); - return typeof cb === "function" ? cb() : void 0; - }, - to: function(dest, data) { - var archive; - archive = (dest === 'search' || dest === 'board' ? Redirect.data.thread : Redirect.data[dest])[data.boardID]; - if (!archive) { - return ''; - } - return Redirect[dest](archive, data); - }, - protocol: function(archive) { - var protocol; - protocol = location.protocol; - if (!$.getOwn(archive, protocol.slice(0, -1))) { - protocol = protocol === 'https:' ? 'http:' : 'https:'; - } - return protocol + "//"; - }, - thread: function(archive, arg) { - var boardID, path, postID, threadID; - boardID = arg.boardID, threadID = arg.threadID, postID = arg.postID; - path = threadID ? boardID + "/thread/" + threadID : boardID + "/post/" + postID; - if (archive.software === 'foolfuuka') { - path += '/'; - } - if (threadID && postID) { - path += archive.software === 'foolfuuka' ? "#" + postID : "#p" + postID; - } - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; - }, - post: function(archive, arg) { - var boardID, postID, protocol, url; - boardID = arg.boardID, postID = arg.postID; - protocol = Redirect.protocol(archive); - url = "" + protocol + archive.domain + "/_/api/chan/post/?board=" + boardID + "&num=" + postID; - if (!Redirect.securityCheck(url)) { - return ''; - } - return url; - }, - file: function(archive, arg) { - var boardID, filename; - boardID = arg.boardID, filename = arg.filename; - if (!filename) { - return ''; - } - if (boardID === 'f') { - filename = encodeURIComponent($.unescape(decodeURIComponent(filename))); - } else { - if (/[sm]\.jpg$/.test(filename)) { - return ''; - } - } - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/full_image/" + filename; - }, - board: function(archive, arg) { - var boardID; - boardID = arg.boardID; - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + boardID + "/"; - }, - search: function(archive, arg) { - var boardID, path, type, value; - boardID = arg.boardID, type = arg.type, value = arg.value; - type = type === 'name' ? 'username' : type === 'MD5' ? 'image' : type; - if (type === 'capcode') { - value = $.getOwn({ - 'Developer': 'dev', - 'Verified': 'ver' - }, value) || value.toLowerCase(); - } else if (type === 'image') { - value = value.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }); - } - value = encodeURIComponent(value); - path = archive.software === 'foolfuuka' ? boardID + "/search/" + type + "/" + value + "/" : type === 'image' ? boardID + "/image/" + value : boardID + "/?task=search2&search_" + type + "=" + value; - return "" + (Redirect.protocol(archive)) + archive.domain + "/" + path; - }, - report: function(boardID) { - var archive, boards, domain, https, j, len, name, ref, reports, software, urls; - urls = []; - ref = Conf['archives']; - for (j = 0, len = ref.length; j < len; j++) { - archive = ref[j]; - software = archive.software, https = archive.https, reports = archive.reports, boards = archive.boards, name = archive.name, domain = archive.domain; - if (software === 'foolfuuka' && https && reports && boards instanceof Array && indexOf.call(boards, boardID) >= 0) { - urls.push([name, "https://" + domain + "/_/api/chan/offsite_report/"]); - } - } - return urls; - }, - securityCheck: function(url) { - return /^https:\/\//.test(url) || location.protocol === 'http:' || Conf['Exempt Archives from Encryption']; - }, - navigate: function(dest, data, alternative) { - var url; - if (!Redirect.data) { - Redirect.init(); - } - url = Redirect.to(dest, data); - if (url && (Redirect.securityCheck(url) || confirm("Redirect to " + url + "?\n\nYour connection will not be encrypted."))) { - return location.replace(url); - } else if (alternative) { - return location.replace(alternative); - } - } - }; - - return Redirect; - -}).call(this); - -Anonymize = (function() { - var Anonymize; - - Anonymize = { - init: function() { - if (!Conf['Anonymize']) { - return; - } - return $.addClass(doc, 'anonymize'); - } - }; - - return Anonymize; - -}).call(this); - -Filter = (function() { - var Filter, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - Filter = { - filters: $.dict(), - init: function() { - var base, base1, boards, err, excludes, file, filter, hide, hl, i, isstring, j, key, len, len1, line, mask, noti, op, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, regexp, stub, top, type, types; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'catalog') && Conf['Filter'])) { - return; - } - if (g.VIEW === 'catalog' && !Conf['Filter in Native Catalog']) { - return; - } - if (!Conf['Filtered Backlinks']) { - $.addClass(doc, 'hide-backlinks'); - } - for (key in Config.filter) { - ref1 = Conf[key].split('\n'); - for (i = 0, len = ref1.length; i < len; i++) { - line = ref1[i]; - if (line[0] === '#') { - continue; - } - if (!(regexp = line.match(/\/(.*)\/(\w*)/))) { - continue; - } - filter = line.replace(regexp[0], ''); - boards = this.parseBoards((ref2 = filter.match(/(?:^|;)\s*boards:([^;]+)/)) != null ? ref2[1] : void 0); - excludes = this.parseBoards((ref3 = filter.match(/(?:^|;)\s*exclude:([^;]+)/)) != null ? ref3[1] : void 0); - if ((isstring = (key === 'uniqueID' || key === 'MD5'))) { - regexp = regexp[1]; - } else { - try { - regexp = RegExp(regexp[1], regexp[2]); - } catch (error) { - err = error; - new Notice('warning', [$.tn("Invalid " + key + " filter:"), $.el('br'), $.tn(line), $.el('br'), $.tn(err.message)], 60); - continue; - } - } - op = ((ref4 = filter.match(/(?:^|;)\s*op:(no|only)/)) != null ? ref4[1] : void 0) || ''; - mask = $.getOwn({ - 'no': 1, - 'only': 2 - }, op) || 0; - file = ((ref5 = filter.match(/(?:^|;)\s*file:(no|only)/)) != null ? ref5[1] : void 0) || ''; - mask = mask | ($.getOwn({ - 'no': 4, - 'only': 8 - }, file) || 0); - stub = (function() { - var ref6; - switch ((ref6 = filter.match(/(?:^|;)\s*stub:(yes|no)/)) != null ? ref6[1] : void 0) { - case 'yes': - return true; - case 'no': - return false; - default: - return Conf['Stubs']; - } - })(); - noti = /(?:^|;)\s*notify/.test(filter); - if ((hl = /(?:^|;)\s*highlight/.test(filter))) { - hl = ((ref6 = filter.match(/(?:^|;)\s*highlight:([\w-]+)/)) != null ? ref6[1] : void 0) || 'filter-highlight'; - top = ((ref7 = filter.match(/(?:^|;)\s*top:(yes|no)/)) != null ? ref7[1] : void 0) || 'yes'; - top = top === 'yes'; - } - if (key === 'general') { - if ((types = filter.match(/(?:^|;)\s*type:([^;]*)/))) { - types = types[1].split(','); - } else { - types = ['subject', 'name', 'filename', 'comment']; - } - } - hide = !(hl || noti); - filter = { - isstring: isstring, - regexp: regexp, - boards: boards, - excludes: excludes, - mask: mask, - hide: hide, - stub: stub, - hl: hl, - top: top, - noti: noti - }; - if (key === 'general') { - for (j = 0, len1 = types.length; j < len1; j++) { - type = types[j]; - ((base = this.filters)[type] || (base[type] = [])).push(filter); - } - } else { - ((base1 = this.filters)[key] || (base1[key] = [])).push(filter); - } - } - } - if (!Object.keys(this.filters).length) { - return; - } - if (g.VIEW === 'catalog') { - return Filter.catalog(); - } else { - return Callbacks.Post.push({ - name: 'Filter', - cb: this.node - }); - } - }, - parseBoards: function(boardsRaw) { - var boardID, boardID2, boards, i, j, len, len1, ref, ref1, ref2, ref3, site, siteFilter, siteID; - if (!boardsRaw) { - return false; - } - if ((boards = Filter.parseBoardsMemo[boardsRaw])) { - return boards; - } - boards = $.dict(); - siteFilter = ''; - ref = boardsRaw.split(','); - for (i = 0, len = ref.length; i < len; i++) { - boardID = ref[i]; - if (indexOf.call(boardID, ':') >= 0) { - ref1 = boardID.split(':').slice(-2), siteFilter = ref1[0], boardID = ref1[1]; - } - ref2 = g.sites; - for (siteID in ref2) { - site = ref2[siteID]; - if (siteID.slice(0, siteFilter.length) === siteFilter) { - if (boardID === 'nsfw' || boardID === 'sfw') { - ref3 = (typeof site.sfwBoards === "function" ? site.sfwBoards(boardID === 'sfw') : void 0) || []; - for (j = 0, len1 = ref3.length; j < len1; j++) { - boardID2 = ref3[j]; - boards[siteID + "/" + boardID2] = true; - } - } else { - boards[siteID + "/" + (encodeURIComponent(boardID))] = true; - } - } - } - } - Filter.parseBoardsMemo[boardsRaw] = boards; - return boards; - }, - parseBoardsMemo: $.dict(), - test: function(post, hideable) { - var board, filter, hide, hl, i, j, key, len, len1, mask, noti, ref, ref1, ref2, site, stub, top, value; - if (hideable == null) { - hideable = true; - } - if (post.filterResults) { - return post.filterResults; - } - hide = false; - stub = true; - hl = void 0; - top = false; - noti = false; - if (QuoteYou.isYou(post)) { - hideable = false; - } - mask = (post.isReply ? 2 : 1); - mask = mask | (post.file ? 4 : 8); - board = post.siteID + "/" + post.boardID; - site = post.siteID + "/*"; - for (key in Filter.filters) { - ref = Filter.values(key, post); - for (i = 0, len = ref.length; i < len; i++) { - value = ref[i]; - ref1 = Filter.filters[key]; - for (j = 0, len1 = ref1.length; j < len1; j++) { - filter = ref1[j]; - if ((filter.boards && !(filter.boards[board] || filter.boards[site])) || (filter.excludes && (filter.excludes[board] || filter.excludes[site])) || (filter.mask & mask) || (filter.isstring ? filter.regexp !== value : !filter.regexp.test(value))) { - continue; - } - if (filter.hide) { - if (hideable) { - hide = true; - stub && (stub = filter.stub); - } - } else { - if (!(hl && (ref2 = filter.hl, indexOf.call(hl, ref2) >= 0))) { - (hl || (hl = [])).push(filter.hl); - } - top || (top = filter.top); - if (filter.noti) { - noti = true; - } - } - } - } - } - if (hide) { - return { - hide: hide, - stub: stub - }; - } else { - return { - hl: hl, - top: top, - noti: noti - }; - } - }, - node: function() { - var hide, hl, noti, ref, stub, top; - if (this.isClone) { - return; - } - ref = Filter.test(this, !this.isFetchedQuote && (this.isReply || g.VIEW === 'index')), hide = ref.hide, stub = ref.stub, hl = ref.hl, top = ref.top, noti = ref.noti; - if (hide) { - if (this.isReply) { - PostHiding.hide(this, stub); - } else { - ThreadHiding.hide(this.thread, stub); - } - } else { - if (hl) { - this.highlights = hl; - $.addClass.apply($, [this.nodes.root].concat(slice.call(hl))); - } - } - if (noti && Unread.posts && (this.ID > Unread.lastReadPost) && !QuoteYou.isYou(this)) { - return Unread.openNotification(this, ' triggered a notification filter'); - } - }, - catalog: function() { - var base, url; - if (!(url = typeof (base = g.SITE.urls).catalogJSON === "function" ? base.catalogJSON(g.BOARD) : void 0)) { - return; - } - Filter.catalogData = $.dict(); - $.ajax(url, { - onloadend: Filter.catalogParse - }); - return Callbacks.CatalogThreadNative.push({ - name: 'Filter', - cb: this.catalogNode - }); - }, - catalogParse: function() { - var i, item, j, len, len1, page, ref, ref1, ref2; - if ((ref = this.status) !== 200 && ref !== 404) { - new Notice('warning', "Failed to fetch catalog JSON data. " + (this.status ? "Error " + this.statusText + " (" + this.status + ")" : 'Connection Error'), 1); - return; - } - ref1 = this.response; - for (i = 0, len = ref1.length; i < len; i++) { - page = ref1[i]; - ref2 = page.threads; - for (j = 0, len1 = ref2.length; j < len1; j++) { - item = ref2[j]; - Filter.catalogData[item.no] = item; - } - } - g.BOARD.threads.forEach(function(thread) { - if (thread.catalogViewNative) { - return Filter.catalogNode.call(thread.catalogViewNative); - } - }); - }, - catalogNode: function() { - var base, hide, hl, ref, ref1, top; - if (!(this.boardID === g.BOARD.ID && Filter.catalogData[this.ID])) { - return; - } - if ((ref = QuoteYou.db) != null ? ref.get({ - siteID: g.SITE.ID, - boardID: this.boardID, - threadID: this.ID, - postID: this.ID - }) : void 0) { - return; - } - ref1 = Filter.test(g.SITE.Build.parseJSON(Filter.catalogData[this.ID], this)), hide = ref1.hide, hl = ref1.hl, top = ref1.top; - if (hide) { - return this.nodes.root.hidden = true; - } else { - if (hl) { - this.highlights = hl; - $.addClass.apply($, [this.nodes.root].concat(slice.call(hl))); - } - if (top) { - $.prepend(this.nodes.root.parentNode, this.nodes.root); - return typeof (base = g.SITE).catalogPin === "function" ? base.catalogPin(this.nodes.root) : void 0; - } - } - }, - isHidden: function(post) { - return !!Filter.test(post).hide; - }, - valueF: { - postID: function(post) { - return ["" + post.ID]; - }, - name: function(post) { - return [post.info.name]; - }, - uniqueID: function(post) { - return [post.info.uniqueID || '']; - }, - tripcode: function(post) { - return [post.info.tripcode]; - }, - capcode: function(post) { - return [post.info.capcode]; - }, - pass: function(post) { - return [post.info.pass]; - }, - email: function(post) { - return [post.info.email]; - }, - subject: function(post) { - return [post.info.subject || (post.isReply ? void 0 : '')]; - }, - comment: function(post) { - var base, ref, ref1; - return [((base = post.info).comment != null ? base.comment : base.comment = (ref = g.sites[post.siteID]) != null ? (ref1 = ref.Build) != null ? typeof ref1.parseComment === "function" ? ref1.parseComment(post.info.commentHTML.innerHTML) : void 0 : void 0 : void 0)]; - }, - flag: function(post) { - return [post.info.flag]; - }, - filename: function(post) { - return post.files.map(function(f) { - return f.name; - }); - }, - dimensions: function(post) { - return post.files.map(function(f) { - return f.dimensions; - }); - }, - filesize: function(post) { - return post.files.map(function(f) { - return f.size; - }); - }, - MD5: function(post) { - return post.files.map(function(f) { - return f.MD5; - }); - } - }, - values: function(key, post) { - if ($.hasOwn(Filter.valueF, key)) { - return Filter.valueF[key](post).filter(function(v) { - return v != null; - }); - } else { - return [ - key.split('+').map(function(k) { - var f; - if ((f = $.getOwn(Filter.valueF, k))) { - return f(post).map(function(v) { - return v || ''; - }).join('\n'); - } else { - return ''; - } - }).join('\n') - ]; - } - }, - addFilter: function(type, re, cb) { - if (!$.hasOwn(Config.filter, type)) { - return; - } - return $.get(type, Conf[type], function(item) { - var save; - save = item[type]; - save = save ? save + "\n" + re : re; - return $.set(type, save, cb); - }); - }, - removeFilters: function(type, res, cb) { - return $.get(type, Conf[type], function(item) { - var save; - save = item[type]; - res = res.map(Filter.escape).join('|'); - save = save.replace(RegExp("(?:$\n|^)(?:" + res + ")$", 'mg'), ''); - return $.set(type, save, cb); - }); - }, - showFilters: function(type) { - var section, select; - Settings.open('Filter'); - section = $('.section-container'); - select = $('select[name=filter]', section); - select.value = type; - Settings.selectFilter.call(select); - return $.onExists(section, 'textarea', function(ta) { - var tl; - tl = ta.textLength; - ta.setSelectionRange(tl, tl); - return ta.focus(); - }); - }, - quickFilterMD5: function() { - var files, filter, links, msg, notice, origin, post; - post = Get.postFromNode(this); - files = post.files.filter(function(f) { - return f.MD5; - }); - if (!files.length) { - return; - } - filter = files.map(function(f) { - return "/" + f.MD5 + "/"; - }).join('\n'); - Filter.addFilter('MD5', filter); - origin = post.origin || post; - if (origin.isReply) { - PostHiding.hide(origin); - } else if (g.VIEW === 'index') { - ThreadHiding.hide(origin.thread); - } - if (!Conf['MD5 Quick Filter Notifications']) { - if (post.nodes.post.getBoundingClientRect().height) { - new Notice('info', 'MD5 filtered.', 2); - } - return; - } - notice = Filter.quickFilterMD5.notice; - if (notice) { - notice.filters.push(filter); - notice.posts.push(origin); - return $('span', notice.el).textContent = notice.filters.length + " MD5s filtered."; - } else { - msg = $.el('div', {innerHTML: "MD5 filtered. [show] [undo]"}); - notice = Filter.quickFilterMD5.notice = new Notice('info', msg, void 0, function() { - return delete Filter.quickFilterMD5.notice; - }); - notice.filters = [filter]; - notice.posts = [origin]; - links = $$('a', msg); - $.on(links[0], 'click', Filter.quickFilterCB.show.bind(notice)); - return $.on(links[1], 'click', Filter.quickFilterCB.undo.bind(notice)); - } - }, - quickFilterCB: { - show: function() { - Filter.showFilters('MD5'); - return this.close(); - }, - undo: function() { - var i, len, post, ref; - Filter.removeFilters('MD5', this.filters); - ref = this.posts; - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - if (post.isReply) { - PostHiding.show(post); - } else if (g.VIEW === 'index') { - ThreadHiding.show(post.thread); - } - } - return this.close(); - } - }, - escape: function(value) { - return value.replace(/\/|\\|\^|\$|\n|\.|\(|\)|\{|\}|\[|\]|\?|\*|\+|\|/g, function(c) { - if (c === '\n') { - return '\\n'; - } else if (c === '\\') { - return '\\\\'; - } else { - return "\\" + c; - } - }); - }, - menu: { - init: function() { - var div, entry, i, len, ref, ref1, type; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Filter'])) { - return; - } - div = $.el('div', { - textContent: 'Filter' - }); - entry = { - el: div, - order: 50, - open: function(post) { - Filter.menu.post = post; - return true; - }, - subEntries: [] - }; - ref1 = [['Name', 'name'], ['Unique ID', 'uniqueID'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Pass Date', 'pass'], ['Email', 'email'], ['Subject', 'subject'], ['Comment', 'comment'], ['Flag', 'flag'], ['Filename', 'filename'], ['Image dimensions', 'dimensions'], ['Filesize', 'filesize'], ['Image MD5', 'MD5']]; - for (i = 0, len = ref1.length; i < len; i++) { - type = ref1[i]; - entry.subEntries.push(Filter.menu.createSubEntry(type[0], type[1])); - } - return Menu.menu.addEntry(entry); - }, - createSubEntry: function(text, type) { - var el; - el = $.el('a', { - href: 'javascript:;', - textContent: text - }); - el.dataset.type = type; - $.on(el, 'click', Filter.menu.makeFilter); - return { - el: el, - open: function(post) { - return Filter.values(type, post).length; - } - }; - }, - makeFilter: function() { - var res, type, values; - type = this.dataset.type; - values = Filter.values(type, Filter.menu.post); - res = values.map(function(value) { - var re; - re = type === 'uniqueID' || type === 'MD5' ? value : Filter.escape(value); - if (type === 'uniqueID' || type === 'MD5') { - return "/" + re + "/"; - } else { - return "/^" + re + "$/"; - } - }).join('\n'); - return Filter.addFilter(type, res, function() { - return Filter.showFilters(type); - }); - } - } - }; - - return Filter; - -}).call(this); - -PostHiding = (function() { - var PostHiding; - - PostHiding = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Reply Hiding Buttons'] && !(Conf['Menu'] && Conf['Reply Hiding Link'])) { - return; - } - if (Conf['Reply Hiding Buttons']) { - $.addClass(doc, "reply-hide"); - } - this.db = new DataBoard('hiddenPosts'); - return Callbacks.Post.push({ - name: 'Reply Hiding', - cb: this.node - }); - }, - isHidden: function(boardID, threadID, postID) { - return !!(PostHiding.db && PostHiding.db.get({ - boardID: boardID, - threadID: threadID, - postID: postID - })); - }, - node: function() { - var button, data, sa, sideArrows; - if (!this.isReply || this.isClone || this.isFetchedQuote) { - return; - } - if (data = PostHiding.db.get({ - boardID: this.board.ID, - threadID: this.thread.ID, - postID: this.ID - })) { - if (data.thisPost) { - PostHiding.hide(this, data.makeStub, data.hideRecursively); - } else { - Recursive.apply(PostHiding.hide, this, data.makeStub, true); - Recursive.add(PostHiding.hide, this, data.makeStub, true); - } - } - if (!Conf['Reply Hiding Buttons']) { - return; - } - button = PostHiding.makeButton(this, 'hide'); - if ((sa = g.SITE.selectors.sideArrows)) { - sideArrows = $(sa, this.nodes.root); - $.replace(sideArrows.firstChild, button); - return sideArrows.className = 'replacedSideArrows'; - } else { - return $.prepend(this.nodes.info, button); - } - }, - menu: { - init: function() { - var apply, div, hideStubLink, makeStub, ref, replies, thisPost; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Menu'] || !Conf['Reply Hiding Link']) { - return; - } - div = $.el('div', { - className: 'hide-reply-link', - textContent: 'Hide' - }); - apply = $.el('a', { - textContent: 'Apply', - href: 'javascript:;' - }); - $.on(apply, 'click', PostHiding.menu.hide); - thisPost = UI.checkbox('thisPost', 'This post', true); - replies = UI.checkbox('replies', 'Hide replies', Conf['Recursive Hiding']); - makeStub = UI.checkbox('makeStub', 'Make stub', Conf['Stubs']); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(post) { - if (!post.isReply || post.isClone || post.isHidden) { - return false; - } - PostHiding.menu.post = post; - return true; - }, - subEntries: [ - { - el: apply - }, { - el: thisPost - }, { - el: replies - }, { - el: makeStub - } - ] - }); - div = $.el('div', { - className: 'show-reply-link', - textContent: 'Show' - }); - apply = $.el('a', { - textContent: 'Apply', - href: 'javascript:;' - }); - $.on(apply, 'click', PostHiding.menu.show); - thisPost = UI.checkbox('thisPost', 'This post', false); - replies = UI.checkbox('replies', 'Show replies', false); - hideStubLink = $.el('a', { - textContent: 'Hide stub', - href: 'javascript:;' - }); - $.on(hideStubLink, 'click', PostHiding.menu.hideStub); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(post) { - var data; - if (!post.isReply || post.isClone || !post.isHidden) { - return false; - } - if (!(data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - }))) { - return false; - } - PostHiding.menu.post = post; - thisPost.firstChild.checked = post.isHidden; - replies.firstChild.checked = (data != null ? data.hideRecursively : void 0) != null ? data.hideRecursively : Conf['Recursive Hiding']; - return true; - }, - subEntries: [ - { - el: apply - }, { - el: thisPost - }, { - el: replies - } - ] - }); - return Menu.menu.addEntry({ - el: hideStubLink, - order: 15, - open: function(post) { - var data; - if (!post.isReply || post.isClone || !post.isHidden) { - return false; - } - if (!(data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - }))) { - return false; - } - return PostHiding.menu.post = post; - } - }); - }, - hide: function() { - var makeStub, parent, post, replies, thisPost; - parent = this.parentNode; - thisPost = $('input[name=thisPost]', parent).checked; - replies = $('input[name=replies]', parent).checked; - makeStub = $('input[name=makeStub]', parent).checked; - post = PostHiding.menu.post; - if (thisPost) { - PostHiding.hide(post, makeStub, replies); - } else if (replies) { - Recursive.apply(PostHiding.hide, post, makeStub, true); - Recursive.add(PostHiding.hide, post, makeStub, true); - } else { - return; - } - PostHiding.saveHiddenState(post, true, thisPost, makeStub, replies); - return $.event('CloseMenu'); - }, - show: function() { - var data, parent, post, replies, thisPost; - parent = this.parentNode; - thisPost = $('input[name=thisPost]', parent).checked; - replies = $('input[name=replies]', parent).checked; - post = PostHiding.menu.post; - if (thisPost) { - PostHiding.show(post, replies); - } else if (replies) { - Recursive.apply(PostHiding.show, post, true); - Recursive.rm(PostHiding.hide, post, true); - } else { - return; - } - if (data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - })) { - PostHiding.saveHiddenState(post, !(thisPost && replies), !thisPost, data.makeStub, !replies); - } - return $.event('CloseMenu'); - }, - hideStub: function() { - var data, post; - post = PostHiding.menu.post; - if (data = PostHiding.db.get({ - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - })) { - PostHiding.show(post, data.hideRecursively); - PostHiding.hide(post, false, data.hideRecursively); - PostHiding.saveHiddenState(post, true, true, false, data.hideRecursively); - } - $.event('CloseMenu'); - } - }, - makeButton: function(post, type) { - var a, span; - span = $.el('span', { - className: "fa fa-" + (type === 'hide' ? 'minus' : 'plus') + "-square-o", - textContent: "" - }); - a = $.el('a', { - className: type + "-reply-button", - href: 'javascript:;' - }); - $.add(a, span); - $.on(a, 'click', PostHiding.toggle); - return a; - }, - saveHiddenState: function(post, isHiding, thisPost, makeStub, hideRecursively) { - var data; - data = { - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID - }; - if (isHiding) { - data.val = { - thisPost: thisPost !== false, - makeStub: makeStub, - hideRecursively: hideRecursively - }; - return PostHiding.db.set(data); - } else { - return PostHiding.db["delete"](data); - } - }, - toggle: function() { - var post; - post = Get.postFromNode(this); - PostHiding[(post.isHidden ? 'show' : 'hide')](post); - return PostHiding.saveHiddenState(post, post.isHidden); - }, - hide: function(post, makeStub, hideRecursively) { - var a, i, len, quotelink, ref; - if (makeStub == null) { - makeStub = Conf['Stubs']; - } - if (hideRecursively == null) { - hideRecursively = Conf['Recursive Hiding']; - } - if (post.isHidden) { - return; - } - post.isHidden = true; - if (hideRecursively) { - Recursive.apply(PostHiding.hide, post, makeStub, true); - Recursive.add(PostHiding.hide, post, makeStub, true); - } - ref = Get.allQuotelinksLinkingTo(post); - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - $.addClass(quotelink, 'filtered'); - } - if (!makeStub) { - post.nodes.root.hidden = true; - return; - } - a = PostHiding.makeButton(post, 'show'); - $.add(a, $.tn(" " + post.info.nameBlock)); - post.nodes.stub = $.el('div', { - className: 'stub' - }); - $.add(post.nodes.stub, a); - if (Conf['Menu']) { - $.add(post.nodes.stub, Menu.makeButton(post)); - } - return $.prepend(post.nodes.root, post.nodes.stub); - }, - show: function(post, showRecursively) { - var i, len, quotelink, ref; - if (showRecursively == null) { - showRecursively = Conf['Recursive Hiding']; - } - if (post.nodes.stub) { - $.rm(post.nodes.stub); - delete post.nodes.stub; - } else { - post.nodes.root.hidden = false; - } - post.isHidden = false; - if (showRecursively) { - Recursive.apply(PostHiding.show, post, true); - Recursive.rm(PostHiding.hide, post); - } - ref = Get.allQuotelinksLinkingTo(post); - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - $.rmClass(quotelink, 'filtered'); - } - } - }; - - return PostHiding; - -}).call(this); - -Recursive = (function() { - var Recursive, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Recursive = { - recursives: $.dict(), - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - return Callbacks.Post.push({ - name: 'Recursive', - cb: this.node - }); - }, - node: function() { - var i, j, k, len, len1, obj, quote, recursive, ref, ref1; - if (this.isClone || this.isFetchedQuote) { - return; - } - ref = this.quotes; - for (j = 0, len = ref.length; j < len; j++) { - quote = ref[j]; - if (obj = Recursive.recursives[quote]) { - ref1 = obj.recursives; - for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { - recursive = ref1[i]; - recursive.apply(null, [this].concat(slice.call(obj.args[i]))); - } - } - } - }, - add: function() { - var args, base, name, obj, post, recursive; - recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - obj = (base = Recursive.recursives)[name = post.fullID] || (base[name] = { - recursives: [], - args: [] - }); - obj.recursives.push(recursive); - return obj.args.push(args); - }, - rm: function(recursive, post) { - var i, j, len, obj, rec, ref; - if (!(obj = Recursive.recursives[post.fullID])) { - return; - } - ref = obj.recursives; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - rec = ref[i]; - if (!(rec === recursive)) { - continue; - } - obj.recursives.splice(i, 1); - obj.args.splice(i, 1); - } - }, - apply: function() { - var args, fullID, post, recursive; - recursive = arguments[0], post = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - fullID = post.fullID; - return g.posts.forEach(function(post) { - if (indexOf.call(post.quotes, fullID) >= 0) { - return recursive.apply(null, [post].concat(slice.call(args))); - } - }); - } - }; - - return Recursive; - -}).call(this); - -ThreadHiding = (function() { - var ThreadHiding; - - ThreadHiding = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'catalog') || !Conf['Thread Hiding Buttons'] && !(Conf['Menu'] && Conf['Thread Hiding Link']) && !Conf['JSON Index']) { - return; - } - this.db = new DataBoard('hiddenThreads'); - if (g.VIEW === 'catalog') { - return this.catalogWatch(); - } - this.catalogSet(g.BOARD); - $.on(d, 'IndexRefreshInternal', this.onIndexRefresh); - if (Conf['Thread Hiding Buttons']) { - $.addClass(doc, 'thread-hide'); - } - return Callbacks.Post.push({ - name: 'Thread Hiding', - cb: this.node - }); - }, - catalogSet: function(board) { - var hiddenThreads, threadID; - if (!($.hasStorage && g.SITE.software === 'yotsuba')) { - return; - } - hiddenThreads = ThreadHiding.db.get({ - boardID: board.ID, - defaultValue: $.dict() - }); - for (threadID in hiddenThreads) { - hiddenThreads[threadID] = true; - } - return localStorage.setItem("4chan-hide-t-" + board, JSON.stringify(hiddenThreads)); - }, - catalogWatch: function() { - if (!($.hasStorage && g.SITE.software === 'yotsuba')) { - return; - } - this.hiddenThreads = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - return Main.ready(function() { - return new MutationObserver(ThreadHiding.catalogSave).observe($.id('threads'), { - attributes: true, - subtree: true, - attributeFilter: ['style'] - }); - }); - }, - catalogSave: function() { - var hiddenThreads2, threadID; - hiddenThreads2 = JSON.parse(localStorage.getItem("4chan-hide-t-" + g.BOARD)) || {}; - for (threadID in hiddenThreads2) { - if (!$.hasOwn(ThreadHiding.hiddenThreads, threadID)) { - ThreadHiding.db.set({ - boardID: g.BOARD.ID, - threadID: threadID, - val: { - makeStub: Conf['Stubs'] - } - }); - } - } - for (threadID in ThreadHiding.hiddenThreads) { - if (!$.hasOwn(hiddenThreads2, threadID)) { - ThreadHiding.db["delete"]({ - boardID: g.BOARD.ID, - threadID: threadID - }); - } - } - return ThreadHiding.hiddenThreads = hiddenThreads2; - }, - isHidden: function(boardID, threadID) { - return !!(ThreadHiding.db && ThreadHiding.db.get({ - boardID: boardID, - threadID: threadID - })); - }, - node: function() { - var data; - if (this.isReply || this.isClone || this.isFetchedQuote) { - return; - } - if (Conf['Thread Hiding Buttons']) { - $.prepend(this.nodes.root, ThreadHiding.makeButton(this.thread, 'hide')); - } - if (data = ThreadHiding.db.get({ - boardID: this.board.ID, - threadID: this.ID - })) { - return ThreadHiding.hide(this.thread, data.makeStub); - } - }, - onIndexRefresh: function() { - return g.BOARD.threads.forEach(function(thread) { - var root; - root = thread.nodes.root; - if (thread.isHidden && thread.stub && !root.contains(thread.stub)) { - return ThreadHiding.makeStub(thread, root); - } - }); - }, - menu: { - init: function() { - var apply, div, hideStubLink, makeStub; - if (g.VIEW !== 'index' || !Conf['Menu'] || !Conf['Thread Hiding Link']) { - return; - } - div = $.el('div', { - className: 'hide-thread-link', - textContent: 'Hide' - }); - apply = $.el('a', { - textContent: 'Apply', - href: 'javascript:;' - }); - $.on(apply, 'click', ThreadHiding.menu.hide); - makeStub = UI.checkbox('Stubs', 'Make stub'); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(arg) { - var isReply, thread; - thread = arg.thread, isReply = arg.isReply; - if (isReply || thread.isHidden || Conf['JSON Index'] && Conf['Index Mode'] === 'catalog') { - return false; - } - ThreadHiding.menu.thread = thread; - return true; - }, - subEntries: [ - { - el: apply - }, { - el: makeStub - } - ] - }); - div = $.el('a', { - className: 'show-thread-link', - textContent: 'Show', - href: 'javascript:;' - }); - $.on(div, 'click', ThreadHiding.menu.show); - Menu.menu.addEntry({ - el: div, - order: 20, - open: function(arg) { - var isReply, thread; - thread = arg.thread, isReply = arg.isReply; - if (isReply || !thread.isHidden || Conf['JSON Index'] && Conf['Index Mode'] === 'catalog') { - return false; - } - ThreadHiding.menu.thread = thread; - return true; - } - }); - hideStubLink = $.el('a', { - textContent: 'Hide stub', - href: 'javascript:;' - }); - $.on(hideStubLink, 'click', ThreadHiding.menu.hideStub); - return Menu.menu.addEntry({ - el: hideStubLink, - order: 15, - open: function(arg) { - var isReply, thread; - thread = arg.thread, isReply = arg.isReply; - if (isReply || !thread.isHidden || Conf['JSON Index'] && Conf['Index Mode'] === 'catalog') { - return false; - } - return ThreadHiding.menu.thread = thread; - } - }); - }, - hide: function() { - var makeStub, thread; - makeStub = $('input', this.parentNode).checked; - thread = ThreadHiding.menu.thread; - ThreadHiding.hide(thread, makeStub); - ThreadHiding.saveHiddenState(thread, makeStub); - return $.event('CloseMenu'); - }, - show: function() { - var thread; - thread = ThreadHiding.menu.thread; - ThreadHiding.show(thread); - ThreadHiding.saveHiddenState(thread); - return $.event('CloseMenu'); - }, - hideStub: function() { - var thread; - thread = ThreadHiding.menu.thread; - ThreadHiding.show(thread); - ThreadHiding.hide(thread, false); - ThreadHiding.saveHiddenState(thread, false); - $.event('CloseMenu'); - } - }, - makeButton: function(thread, type) { - var a; - a = $.el('a', { - className: type + "-thread-button", - href: 'javascript:;' - }); - $.extend(a, {innerHTML: ""}); - a.dataset.fullID = thread.fullID; - $.on(a, 'click', ThreadHiding.toggle); - return a; - }, - makeStub: function(thread, root) { - var a, numReplies, summary, threadDivider; - numReplies = $$(g.SITE.selectors.replyOriginal, root).length; - if (summary = $(g.SITE.selectors.summary, root)) { - numReplies += +summary.textContent.match(/\d+/); - } - a = ThreadHiding.makeButton(thread, 'show'); - $.add(a, $.tn(" " + thread.OP.info.nameBlock + " (" + (numReplies === 1 ? '1 reply' : numReplies + " replies") + ")")); - thread.stub = $.el('div', { - className: 'stub' - }); - if (Conf['Menu']) { - $.add(thread.stub, [a, Menu.makeButton(thread.OP)]); - } else { - $.add(thread.stub, a); - } - $.prepend(root, thread.stub); - if ((threadDivider = $(g.SITE.selectors.threadDivider, root))) { - return $.addClass(threadDivider, 'threadDivider'); - } - }, - saveHiddenState: function(thread, makeStub) { - if (thread.isHidden) { - ThreadHiding.db.set({ - boardID: thread.board.ID, - threadID: thread.ID, - val: { - makeStub: makeStub - } - }); - } else { - ThreadHiding.db["delete"]({ - boardID: thread.board.ID, - threadID: thread.ID - }); - } - return ThreadHiding.catalogSet(thread.board); - }, - toggle: function(thread) { - if (!(thread instanceof Thread)) { - thread = g.threads.get(this.dataset.fullID); - } - if (thread.isHidden) { - ThreadHiding.show(thread); - } else { - ThreadHiding.hide(thread); - } - return ThreadHiding.saveHiddenState(thread); - }, - hide: function(thread, makeStub) { - var threadRoot; - if (makeStub == null) { - makeStub = Conf['Stubs']; - } - if (thread.isHidden) { - return; - } - threadRoot = thread.nodes.root; - thread.isHidden = true; - Index.updateHideLabel(); - if (thread.catalogView && !Index.showHiddenThreads) { - $.rm(thread.catalogView.nodes.root); - $.event('PostsRemoved', null, Index.root); - } - if (!makeStub) { - return threadRoot.hidden = true; - } - return ThreadHiding.makeStub(thread, threadRoot); - }, - show: function(thread) { - var threadRoot; - if (thread.stub) { - $.rm(thread.stub); - delete thread.stub; - } - threadRoot = thread.nodes.root; - threadRoot.hidden = thread.isHidden = false; - Index.updateHideLabel(); - if (thread.catalogView && Index.showHiddenThreads) { - $.rm(thread.catalogView.nodes.root); - return $.event('PostsRemoved', null, Index.root); - } - } - }; - - return ThreadHiding; - -}).call(this); - -BoardConfig = (function() { - var BoardConfig; - - BoardConfig = { - cbs: [], - init: function() { - var boards, now, ref; - if (g.SITE.software !== 'yotsuba') { - return; - } - now = Date.now(); - if (!((now - 2 * $.HOUR < (ref = Conf['boardConfig'].lastChecked || 0) && ref <= now))) { - return $.ajax(location.protocol + "//a.4cdn.org/boards.json", { - onloadend: this.load - }); - } else { - boards = Conf['boardConfig'].boards; - return this.set(boards); - } - }, - load: function() { - var board, boards, err, i, len, ref; - if (this.status === 200 && this.response && this.response.boards) { - boards = $.dict(); - ref = this.response.boards; - for (i = 0, len = ref.length; i < len; i++) { - board = ref[i]; - boards[board.board] = board; - } - $.set('boardConfig', { - boards: boards, - lastChecked: Date.now() - }); - } else { - boards = Conf['boardConfig'].boards; - err = (function() { - switch (this.status) { - case 0: - return 'Connection Error'; - case 200: - return 'Invalid Data'; - default: - return "Error " + this.statusText + " (" + this.status + ")"; - } - }).call(this); - new Notice('warning', "Failed to load board configuration. " + err, 20); - } - return BoardConfig.set(boards); - }, - set: function(boards1) { - var ID, board, cb, i, len, ref, ref1; - this.boards = boards1; - ref = g.boards; - for (ID in ref) { - board = ref[ID]; - board.config = this.boards[ID] || {}; - } - ref1 = this.cbs; - for (i = 0, len = ref1.length; i < len; i++) { - cb = ref1[i]; - $.queueTask(cb); - } - }, - ready: function(cb) { - if (this.boards) { - return cb(); - } else { - return this.cbs.push(cb); - } - }, - sfwBoards: function(sfw) { - var board, data, ref, results; - ref = this.boards || Conf['boardConfig'].boards; - results = []; - for (board in ref) { - data = ref[board]; - if (!!data.ws_board === sfw) { - results.push(board); - } - } - return results; - }, - isSFW: function(board) { - var ref; - return !!((ref = (this.boards || Conf['boardConfig'].boards)[board]) != null ? ref.ws_board : void 0); - }, - domain: function(board) { - return "boards." + (BoardConfig.isSFW(board) ? '4channel' : '4chan') + ".org"; - }, - isArchived: function(board) { - var data; - data = (this.boards || Conf['boardConfig'].boards)[board]; - return !data || data.is_archived; - }, - noAudio: function(boardID) { - var boards; - if (g.SITE.software !== 'yotsuba') { - return false; - } - boards = this.boards || Conf['boardConfig'].boards; - return boards && boards[boardID] && !boards[boardID].webm_audio; - }, - title: function(boardID) { - var ref, ref1; - return ((ref = this.boards || Conf['boardConfig'].boards) != null ? (ref1 = ref[boardID]) != null ? ref1.title : void 0 : void 0) || ''; - } - }; - - return BoardConfig; - -}).call(this); - -Get = (function() { - var Get, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Get = { - url: function() { - var IDs, args, f, site, type; - type = arguments[0], IDs = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : []; - if ((site = g.sites[IDs.siteID]) && (f = $.getOwn(site.urls, type))) { - return f.apply(null, [IDs].concat(slice.call(args))); - } else { - return void 0; - } - }, - threadExcerpt: function(thread) { - var OP, excerpt, ref, ref1; - OP = thread.OP; - excerpt = ("/" + (decodeURIComponent(thread.board.ID)) + "/ - ") + (((ref = OP.info.subject) != null ? ref.trim() : void 0) || OP.commentDisplay().replace(/\n+/g, ' // ') || ((ref1 = OP.file) != null ? ref1.name : void 0) || ("No." + OP)); - if (excerpt.length > 73) { - return excerpt.slice(0, 70) + "..."; - } - return excerpt; - }, - threadFromRoot: function(root) { - var board; - if (root == null) { - return null; - } - board = root.dataset.board; - return g.threads.get((board ? encodeURIComponent(board) : g.BOARD.ID) + "." + (root.id.match(/\d*$/)[0])); - }, - threadFromNode: function(node) { - return Get.threadFromRoot($.x("ancestor-or-self::" + g.SITE.xpath.thread, node)); - }, - postFromRoot: function(root) { - var index, post; - if (root == null) { - return null; - } - post = g.posts.get(root.dataset.fullID); - index = root.dataset.clone; - if (index) { - return post.clones[+index]; - } else { - return post; - } - }, - postFromNode: function(root) { - return Get.postFromRoot($.x("ancestor-or-self::" + g.SITE.xpath.postContainer + "[1]", root)); - }, - postDataFromLink: function(link) { - var boardID, match, postID, ref, ref1, threadID; - if (link.dataset.postID) { - ref = link.dataset, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - threadID || (threadID = 0); - } else { - match = link.href.match(g.SITE.regexp.quotelink); - ref1 = match.slice(1), boardID = ref1[0], threadID = ref1[1], postID = ref1[2]; - postID || (postID = threadID); - } - return { - boardID: boardID, - threadID: +threadID, - postID: +postID - }; - }, - allQuotelinksLinkingTo: function(post) { - var fullID, handleQuotes, i, len, posts, qPost, quote, quotelinks, ref; - quotelinks = []; - posts = g.posts; - fullID = post.fullID; - handleQuotes = function(qPost, type) { - var clone, i, len, ref; - quotelinks.push.apply(quotelinks, qPost.nodes[type]); - ref = qPost.clones; - for (i = 0, len = ref.length; i < len; i++) { - clone = ref[i]; - quotelinks.push.apply(quotelinks, clone.nodes[type]); - } - }; - posts.forEach(function(qPost) { - if (indexOf.call(qPost.quotes, fullID) >= 0) { - return handleQuotes(qPost, 'quotelinks'); - } - }); - if (Conf['Quote Backlinks']) { - ref = post.quotes; - for (i = 0, len = ref.length; i < len; i++) { - quote = ref[i]; - if (qPost = posts.get(quote)) { - handleQuotes(qPost, 'backlinks'); - } - } - } - return quotelinks.filter(function(quotelink) { - var boardID, postID, ref1; - ref1 = Get.postDataFromLink(quotelink), boardID = ref1.boardID, postID = ref1.postID; - return boardID === post.board.ID && postID === post.ID; - }); - } - }; - - return Get; - -}).call(this); - -Header = (function() { - var Header, - slice = [].slice; - - Header = { - init: function() { - var barFixedToggler, barPositionToggler, box, cs, customNavToggler, editCustomNav, footerToggler, headerToggler, linkJustifyToggler, menuButton, scrollHeaderToggler, shortcutToggler; - $.onExists(doc, 'body', (function(_this) { - return function() { - if (!Main.isThisPageLegit()) { - return; - } - $.add(_this.bar, [_this.noticesRoot, _this.toggle]); - $.prepend(d.body, _this.bar); - $.add(d.body, Header.hover); - return _this.setBarPosition(Conf['Bottom Header']); - }; - })(this)); - this.menu = new UI.Menu('header'); - menuButton = $.el('span', { - className: 'menu-button' - }); - $.extend(menuButton, {innerHTML: ""}); - box = UI.checkbox; - barFixedToggler = box('Fixed Header', 'Fixed Header'); - headerToggler = box('Header auto-hide', 'Auto-hide header'); - scrollHeaderToggler = box('Header auto-hide on scroll', 'Auto-hide header on scroll'); - barPositionToggler = box('Bottom Header', 'Bottom header'); - linkJustifyToggler = box('Centered links', 'Centered links'); - customNavToggler = box('Custom Board Navigation', 'Custom board navigation'); - footerToggler = box('Bottom Board List', 'Hide bottom board list'); - shortcutToggler = box('Shortcut Icons', 'Shortcut Icons'); - editCustomNav = $.el('a', { - textContent: 'Edit custom board navigation', - href: 'javascript:;' - }); - this.barFixedToggler = barFixedToggler.firstElementChild; - this.scrollHeaderToggler = scrollHeaderToggler.firstElementChild; - this.barPositionToggler = barPositionToggler.firstElementChild; - this.linkJustifyToggler = linkJustifyToggler.firstElementChild; - this.headerToggler = headerToggler.firstElementChild; - this.footerToggler = footerToggler.firstElementChild; - this.shortcutToggler = shortcutToggler.firstElementChild; - this.customNavToggler = customNavToggler.firstElementChild; - $.on(menuButton, 'click', this.menuToggle); - $.on(this.headerToggler, 'change', this.toggleBarVisibility); - $.on(this.barFixedToggler, 'change', this.toggleBarFixed); - $.on(this.barPositionToggler, 'change', this.toggleBarPosition); - $.on(this.scrollHeaderToggler, 'change', this.toggleHideBarOnScroll); - $.on(this.linkJustifyToggler, 'change', this.toggleLinkJustify); - $.on(this.footerToggler, 'change', this.toggleFooterVisibility); - $.on(this.shortcutToggler, 'change', this.toggleShortcutIcons); - $.on(this.customNavToggler, 'change', this.toggleCustomNav); - $.on(editCustomNav, 'click', this.editCustomNav); - this.setBarFixed(Conf['Fixed Header']); - this.setHideBarOnScroll(Conf['Header auto-hide on scroll']); - this.setBarVisibility(Conf['Header auto-hide']); - this.setLinkJustify(Conf['Centered links']); - this.setShortcutIcons(Conf['Shortcut Icons']); - this.setFooterVisibility(Conf['Bottom Board List']); - $.sync('Fixed Header', this.setBarFixed); - $.sync('Header auto-hide on scroll', this.setHideBarOnScroll); - $.sync('Bottom Header', this.setBarPosition); - $.sync('Shortcut Icons', this.setShortcutIcons); - $.sync('Header auto-hide', this.setBarVisibility); - $.sync('Centered links', this.setLinkJustify); - $.sync('Bottom Board List', this.setFooterVisibility); - this.addShortcut('menu', menuButton, 900); - this.menu.addEntry({ - el: $.el('span', { - textContent: 'Header' - }), - order: 107, - subEntries: [ - { - el: barFixedToggler - }, { - el: headerToggler - }, { - el: scrollHeaderToggler - }, { - el: barPositionToggler - }, { - el: linkJustifyToggler - }, { - el: footerToggler - }, { - el: shortcutToggler - }, { - el: customNavToggler - }, { - el: editCustomNav - } - ] - }); - $.on(window, 'load popstate', Header.hashScroll); - $.on(d, 'CreateNotification', this.createNotification); - this.setBoardList(); - $.onExists(doc, g.SITE.selectors.boardList + " + *", Header.generateFullBoardList); - Main.ready(function() { - var a, absbot, footer, i, len, ref; - if (g.SITE.software === 'yotsuba' && !(footer = $.id('boardNavDesktopFoot'))) { - if (!(absbot = $.id('absbot'))) { - return; - } - footer = $.id('boardNavDesktop').cloneNode(true); - footer.id = 'boardNavDesktopFoot'; - $('#navtopright', footer).id = 'navbotright'; - $('#settingsWindowLink', footer).id = 'settingsWindowLinkBot'; - $.before(absbot, footer); - $.global(function() { - return window.cloneTopNav = function() {}; - }); - } - if ((Header.bottomBoardList = $(g.SITE.selectors.boardListBottom))) { - ref = $$('a', Header.bottomBoardList); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - if (a.hostname === location.hostname && a.pathname.split('/')[1] === g.BOARD.ID) { - a.className = 'current'; - } - } - return CatalogLinks.setLinks(Header.bottomBoardList); - } - }); - if (g.SITE.software === 'yotsuba' && (g.VIEW === 'catalog' || !Conf['Disable Native Extension'])) { - cs = $.el('a', { - href: 'javascript:;' - }); - if (g.VIEW === 'catalog') { - cs.title = cs.textContent = 'Catalog Settings'; - cs.className = 'fa fa-book'; - } else { - cs.title = cs.textContent = '4chan Settings'; - cs.className = 'native-settings'; - } - $.on(cs, 'click', function() { - return $.id('settingsWindowLink').click(); - }); - this.addShortcut('native', cs, 810); - } - return this.enableDesktopNotifications(); - }, - bar: $.el('div', { - id: 'header-bar' - }), - noticesRoot: $.el('div', { - id: 'notifications' - }), - shortcuts: $.el('span', { - id: 'shortcuts' - }), - hover: $.el('div', { - id: 'hoverUI' - }), - toggle: $.el('div', { - id: 'scroll-marker' - }), - setBoardList: function() { - var boardList, btn; - Header.boardList = boardList = $.el('span', { - id: 'board-list' - }); - $.extend(boardList, {innerHTML: ""}); - btn = $('.hide-board-list-button', boardList); - $.on(btn, 'click', Header.toggleBoardList); - $.prepend(Header.bar, [Header.boardList, Header.shortcuts]); - Header.setCustomNav(Conf['Custom Board Navigation']); - Header.generateBoardList(Conf['boardnav']); - $.sync('Custom Board Navigation', Header.setCustomNav); - return $.sync('boardnav', Header.generateBoardList); - }, - generateFullBoardList: function() { - var a, fullBoardList, i, len, nodes, ref; - if (g.SITE.transformBoardList) { - nodes = g.SITE.transformBoardList(); - } else { - nodes = slice.call($(g.SITE.selectors.boardList).cloneNode(true).childNodes); - } - fullBoardList = $('.boardList', Header.boardList); - $.add(fullBoardList, nodes); - ref = $$('a', fullBoardList); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - if (a.hostname === location.hostname && a.pathname.split('/')[1] === g.BOARD.ID) { - a.className = 'current'; - } - } - return CatalogLinks.setLinks(fullBoardList); - }, - generateBoardList: function(boardnav) { - var list, nodes, re, t; - list = $('#custom-board-list', Header.boardList); - $.rmAll(list); - if (!boardnav) { - return; - } - boardnav = boardnav.replace(/(\r\n|\n|\r)/g, ' '); - re = /[\w@]+(-(all|title|replace|full|index|catalog|archive|expired|nt|(mode|sort|text):"[^"]+"(,"[^"]+")?))*|[^\w@]+/g; - nodes = (function() { - var i, len, ref, results; - ref = boardnav.match(re); - results = []; - for (i = 0, len = ref.length; i < len; i++) { - t = ref[i]; - results.push(Header.mapCustomNavigation(t)); - } - return results; - })(); - $.add(list, nodes); - return CatalogLinks.setLinks(list); - }, - mapCustomNavigation: function(t) { - var a, boardID, href, indexOptions, m, ref, ref1, text, url, urlIC; - if (/^[^\w@]/.test(t)) { - return $.tn(t); - } - text = url = null; - t = t.replace(/-text:"([^"]+)"(?:,"([^"]+)")?/g, function(m0, m1, m2) { - text = m1; - url = m2; - return ''; - }); - indexOptions = []; - t = t.replace(/-(?:mode|sort):"([^"]+)"/g, function(m0, m1) { - indexOptions.push(m1.toLowerCase().replace(/\ /g, '-')); - return ''; - }); - indexOptions = indexOptions.join('/'); - if (/^toggle-all/.test(t)) { - a = $.el('a', { - className: 'show-board-list-button', - textContent: text || '+', - href: 'javascript:;' - }); - $.on(a, 'click', Header.toggleBoardList); - return a; - } - if (/^external/.test(t)) { - a = $.el('a', { - href: url || 'javascript:;', - textContent: text || '+', - className: 'external' - }); - if (/-nt/.test(t)) { - a.target = '_blank'; - a.rel = 'noopener'; - } - return a; - } - boardID = t.split('-')[0]; - if (boardID === 'current') { - if ((ref = location.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') { - boardID = g.BOARD.ID; - } else { - a = $.el('a', { - href: "/" + g.BOARD.ID + "/", - textContent: text || decodeURIComponent(g.BOARD.ID), - className: 'current' - }); - if (/-nt/.test(t)) { - a.target = '_blank'; - a.rel = 'noopener'; - } - if (/-index/.test(t)) { - a.dataset.only = 'index'; - } else if (/-catalog/.test(t)) { - a.dataset.only = 'catalog'; - a.href += 'catalog.html'; - } else if (/-(archive|expired)/.test(t)) { - a = a.firstChild; - } - return a; - } - } - a = (function() { - var ref1, urlV; - if (boardID === '@') { - return $.el('a', { - href: 'https://twitter.com/4chan', - title: '4chan Twitter', - textContent: '@' - }); - } - a = $.el('a', { - href: "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/", - textContent: boardID, - title: BoardConfig.title(boardID) - }); - if (((ref1 = g.VIEW) === 'catalog' || ref1 === 'archive') && (urlV = Get.url(g.VIEW, { - siteID: '4chan.org', - boardID: boardID - }))) { - a.href = urlV; - } - if (a.hostname === location.hostname && boardID === g.BOARD.ID) { - a.className = 'current'; - } - return a; - })(); - a.textContent = /-title/.test(t) || /-replace/.test(t) && a.hostname === location.hostname && boardID === g.BOARD.ID ? a.title || a.textContent : /-full/.test(t) ? ("/" + boardID + "/") + (a.title ? " - " + a.title : '') : text || boardID; - if (m = t.match(/-(index|catalog)/)) { - urlIC = CatalogLinks[m[1]]({ - siteID: '4chan.org', - boardID: boardID - }); - if (urlIC) { - a.dataset.only = m[1]; - a.href = urlIC; - if (m[1] === 'catalog') { - $.addClass(a, 'catalog'); - } - } else { - return a.firstChild; - } - } - if (Conf['JSON Index'] && indexOptions) { - a.dataset.indexOptions = indexOptions; - if (((ref1 = a.hostname) === 'boards.4chan.org' || ref1 === 'boards.4channel.org') && a.pathname.split('/')[2] === '') { - a.href += (a.hash ? '/' : '#') + indexOptions; - } - } - if (/-archive/.test(t)) { - if (href = Redirect.to('board', { - boardID: boardID - })) { - a.href = href; - } else { - return a.firstChild; - } - } - if (/-expired/.test(t)) { - if (BoardConfig.isArchived(boardID)) { - a.href = "//" + (BoardConfig.domain(boardID)) + "/" + boardID + "/archive"; - } else { - return a.firstChild; - } - } - if (/-nt/.test(t)) { - a.target = '_blank'; - a.rel = 'noopener'; - } - if (boardID === '@') { - $.addClass(a, 'navSmall'); - } - return a; - }, - toggleBoardList: function() { - var bar, custom, full, showBoardList; - bar = Header.bar; - custom = $('#custom-board-list', bar); - full = $('#full-board-list', bar); - showBoardList = !full.hidden; - custom.hidden = !showBoardList; - return full.hidden = showBoardList; - }, - setLinkJustify: function(centered) { - Header.linkJustifyToggler.checked = centered; - if (centered) { - return $.addClass(doc, 'centered-links'); - } else { - return $.rmClass(doc, 'centered-links'); - } - }, - toggleLinkJustify: function() { - var centered; - $.event('CloseMenu'); - centered = this.nodeName === 'INPUT' ? this.checked : void 0; - Header.setLinkJustify(centered); - return $.set('Centered links', centered); - }, - setBarFixed: function(fixed) { - Header.barFixedToggler.checked = fixed; - if (fixed) { - $.addClass(doc, 'fixed'); - return $.addClass(Header.bar, 'dialog'); - } else { - $.rmClass(doc, 'fixed'); - return $.rmClass(Header.bar, 'dialog'); - } - }, - toggleBarFixed: function() { - $.event('CloseMenu'); - Header.setBarFixed(this.checked); - Conf['Fixed Header'] = this.checked; - return $.set('Fixed Header', this.checked); - }, - setShortcutIcons: function(show) { - Header.shortcutToggler.checked = show; - if (show) { - return $.addClass(doc, 'shortcut-icons'); - } else { - return $.rmClass(doc, 'shortcut-icons'); - } - }, - toggleShortcutIcons: function() { - $.event('CloseMenu'); - Header.setShortcutIcons(this.checked); - Conf['Shortcut Icons'] = this.checked; - return $.set('Shortcut Icons', this.checked); - }, - setBarVisibility: function(hide) { - Header.headerToggler.checked = hide; - $.event('CloseMenu'); - (hide ? $.addClass : $.rmClass)(Header.bar, 'autohide'); - return (hide ? $.addClass : $.rmClass)(doc, 'autohide'); - }, - toggleBarVisibility: function() { - var hide, message; - hide = this.nodeName === 'INPUT' ? this.checked : !$.hasClass(Header.bar, 'autohide'); - Conf['Header auto-hide'] = hide; - $.set('Header auto-hide', hide); - Header.setBarVisibility(hide); - message = "The header bar will " + (hide ? 'automatically hide itself.' : 'remain visible.'); - return new Notice('info', message, 2); - }, - setHideBarOnScroll: function(hide) { - Header.scrollHeaderToggler.checked = hide; - if (hide) { - $.on(window, 'scroll', Header.hideBarOnScroll); - return; - } - $.off(window, 'scroll', Header.hideBarOnScroll); - $.rmClass(Header.bar, 'scroll'); - return Header.bar.classList.toggle('autohide', Conf['Header auto-hide']); - }, - toggleHideBarOnScroll: function() { - var hide; - hide = this.checked; - $.cb.checked.call(this); - return Header.setHideBarOnScroll(hide); - }, - hideBarOnScroll: function() { - var offsetY; - offsetY = window.pageYOffset; - if (offsetY > (Header.previousOffset || 0)) { - $.addClass(Header.bar, 'autohide', 'scroll'); - } else { - $.rmClass(Header.bar, 'autohide', 'scroll'); - } - return Header.previousOffset = offsetY; - }, - setBarPosition: function(bottom) { - var args, ref; - if ((ref = Header.barPositionToggler) != null) { - ref.checked = bottom; - } - $.event('CloseMenu'); - args = bottom ? ['bottom-header', 'top-header', 'after'] : ['top-header', 'bottom-header', 'add']; - $.addClass(doc, args[0]); - $.rmClass(doc, args[1]); - return $[args[2]](Header.bar, Header.noticesRoot); - }, - toggleBarPosition: function() { - $.cb.checked.call(this); - return Header.setBarPosition(this.checked); - }, - setFooterVisibility: function(hide) { - Header.footerToggler.checked = hide; - return doc.classList.toggle('hide-bottom-board-list', hide); - }, - toggleFooterVisibility: function() { - var hide, message; - $.event('CloseMenu'); - hide = this.nodeName === 'INPUT' ? this.checked : $.hasClass(doc, 'hide-bottom-board-list'); - Header.setFooterVisibility(hide); - $.set('Bottom Board List', hide); - message = hide ? 'The bottom navigation will now be hidden.' : 'The bottom navigation will remain visible.'; - return new Notice('info', message, 2); - }, - setCustomNav: function(show) { - var btn, cust, full, ref; - Header.customNavToggler.checked = show; - cust = $('#custom-board-list', Header.bar); - full = $('#full-board-list', Header.bar); - btn = $('.hide-board-list-container', full); - return ref = show ? [false, true, false] : [true, false, true], cust.hidden = ref[0], full.hidden = ref[1], btn.hidden = ref[2], ref; - }, - toggleCustomNav: function() { - $.cb.checked.call(this); - return Header.setCustomNav(this.checked); - }, - editCustomNav: function() { - var settings; - Settings.open('Advanced'); - settings = $.id('fourchanx-settings'); - return $('[name=boardnav]', settings).focus(); - }, - hashScroll: function(e) { - var el, hash; - if (e) { - if (e.state) { - return; - } - if (!history.state) { - history.replaceState({}, ''); - } - } - if ((hash = location.hash.slice(1))) { - ReplyPruning.showIfHidden(hash); - if ((el = $.id(hash))) { - return $.queueTask(function() { - return Header.scrollTo(el); - }); - } - } - }, - scrollTo: function(root, down, needed) { - var height, x; - if (!root.offsetParent) { - return; - } - if (down) { - x = Header.getBottomOf(root); - if (Conf['Fixed Header'] && Conf['Header auto-hide on scroll'] && Conf['Bottom header']) { - height = Header.bar.getBoundingClientRect().height; - if (x <= 0) { - if (!Header.isHidden()) { - x += height; - } - } else { - if (Header.isHidden()) { - x -= height; - } - } - } - if (!(needed && x >= 0)) { - return window.scrollBy(0, -x); - } - } else { - x = Header.getTopOf(root); - if (Conf['Fixed Header'] && Conf['Header auto-hide on scroll'] && !Conf['Bottom header']) { - height = Header.bar.getBoundingClientRect().height; - if (x >= 0) { - if (!Header.isHidden()) { - x += height; - } - } else { - if (Header.isHidden()) { - x -= height; - } - } - } - if (!(needed && x >= 0)) { - return window.scrollBy(0, x); - } - } - }, - scrollToIfNeeded: function(root, down) { - return Header.scrollTo(root, down, true); - }, - getTopOf: function(root) { - var headRect, top; - top = root.getBoundingClientRect().top; - if (Conf['Fixed Header'] && !Conf['Bottom Header']) { - headRect = Header.toggle.getBoundingClientRect(); - top -= headRect.top + headRect.height; - } - return top; - }, - getBottomOf: function(root) { - var bottom, clientHeight, headRect; - clientHeight = doc.clientHeight; - bottom = clientHeight - root.getBoundingClientRect().bottom; - if (Conf['Fixed Header'] && Conf['Bottom Header']) { - headRect = Header.toggle.getBoundingClientRect(); - bottom -= clientHeight - headRect.bottom + headRect.height; - } - return bottom; - }, - isNodeVisible: function(node) { - var height; - if (d.hidden || !doc.contains(node)) { - return false; - } - height = node.getBoundingClientRect().height; - return Header.getTopOf(node) + height >= 0 && Header.getBottomOf(node) + height >= 0; - }, - isHidden: function() { - var top; - top = Header.bar.getBoundingClientRect().top; - if (Conf['Bottom header']) { - return top === doc.clientHeight; - } else { - return top < 0; - } - }, - addShortcut: function(id, el, index) { - var i, item, len, ref, shortcut; - shortcut = $.el('span', { - id: "shortcut-" + id, - className: 'shortcut brackets-wrap' - }); - $.add(shortcut, el); - shortcut.dataset.index = index; - ref = $$('[data-index]', Header.shortcuts); - for (i = 0, len = ref.length; i < len; i++) { - item = ref[i]; - if (!(+item.dataset.index > +index)) { - continue; - } - $.before(item, shortcut); - return; - } - return $.add(Header.shortcuts, shortcut); - }, - rmShortcut: function(el) { - return $.rm(el.parentElement); - }, - menuToggle: function(e) { - return Header.menu.toggle(e, this, g); - }, - createNotification: function(e) { - var content, lifetime, notice, ref, type; - ref = e.detail, type = ref.type, content = ref.content, lifetime = ref.lifetime; - return notice = new Notice(type, content, lifetime); - }, - areNotificationsEnabled: false, - enableDesktopNotifications: function() { - var authorize, disable, el, notice, ref; - if (!(window.Notification && Conf['Desktop Notifications'])) { - return; - } - switch (Notification.permission) { - case 'granted': - Header.areNotificationsEnabled = true; - return; - case 'denied': - return; - } - el = $.el('span', {innerHTML: "4chan X needs your permission to show desktop notifications. [FAQ]
    or "}); - ref = $$('button', el), authorize = ref[0], disable = ref[1]; - $.on(authorize, 'click', function() { - return Notification.requestPermission(function(status) { - Header.areNotificationsEnabled = status === 'granted'; - if (status === 'default') { - return; - } - return notice.close(); - }); - }); - $.on(disable, 'click', function() { - $.set('Desktop Notifications', false); - return notice.close(); - }); - return notice = new Notice('info', el); - } - }; - - return Header; - -}).call(this); - -Index = (function() { - var Index, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Index = { - showHiddenThreads: false, - changed: {}, - enabledOn: function(arg) { - var boardID, siteID; - siteID = arg.siteID, boardID = arg.boardID; - return Conf['JSON Index'] && g.sites[siteID].software === 'yotsuba' && boardID !== 'f'; - }, - init: function() { - var arr, entries, i, input, inputs, k, l, label, len1, len2, name, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, select, sortEntry, tRaw, watchSettings; - if (g.VIEW !== 'index') { - return; - } - $.one(d, '4chanXInitFinished', this.cb.initFinished); - $.on(d, 'PostsInserted', this.cb.postsInserted); - if (!this.enabledOn(g.BOARD)) { - return; - } - this.enabled = true; - Callbacks.Post.push({ - name: 'Index Page Numbers', - cb: this.node - }); - Callbacks.CatalogThread.push({ - name: 'Catalog Features', - cb: this.catalogNode - }); - this.search = ((ref = history.state) != null ? ref.searched : void 0) || ''; - if ((ref1 = history.state) != null ? ref1.mode : void 0) { - Conf['Index Mode'] = (ref2 = history.state) != null ? ref2.mode : void 0; - } - this.currentSort = (ref3 = history.state) != null ? ref3.sort : void 0; - this.currentSort || (this.currentSort = typeof Conf['Index Sort'] === 'object' ? Conf['Index Sort'][g.BOARD.ID] || 'bump' : Conf['Index Sort']); - this.currentPage = this.getCurrentPage(); - this.processHash(); - $.addClass(doc, 'index-loading', (Conf['Index Mode'].replace(/\ /g, '-')) + "-mode"); - $.on(window, 'popstate', this.cb.popstate); - $.on(d, 'scroll', this.scroll); - $.on(d, 'SortIndex', this.cb.resort); - this.button = $.el('a', { - className: 'fa fa-refresh', - title: 'Refresh', - href: 'javascript:;', - textContent: 'Refresh Index' - }); - $.on(this.button, 'click', function() { - return Index.update(); - }); - Header.addShortcut('index-refresh', this.button, 590); - entries = []; - this.inputs = inputs = $.dict(); - ref4 = Config.Index; - for (name in ref4) { - arr = ref4[name]; - if (!(arr instanceof Array)) { - continue; - } - label = UI.checkbox(name, "" + name[0] + (name.slice(1).toLowerCase())); - label.title = arr[1]; - entries.push({ - el: label - }); - input = label.firstChild; - $.on(input, 'change', $.cb.checked); - inputs[name] = input; - } - $.on(inputs['Show Replies'], 'change', this.cb.replies); - $.on(inputs['Catalog Hover Expand'], 'change', this.cb.hover); - $.on(inputs['Pin Watched Threads'], 'change', this.cb.resort); - $.on(inputs['Anchor Hidden Threads'], 'change', this.cb.resort); - watchSettings = function(e) { - if ((input = $.getOwn(inputs, e.target.name))) { - input.checked = e.target.checked; - return $.event('change', null, input); - } - }; - $.on(d, 'OpenSettings', function() { - return $.on($.id('fourchanx-settings'), 'change', watchSettings); - }); - sortEntry = UI.checkbox('Per-Board Sort Type', 'Per-board sort type', typeof Conf['Index Sort'] === 'object'); - sortEntry.title = 'Set the sorting order of each board independently.'; - $.on(sortEntry.firstChild, 'change', this.cb.perBoardSort); - entries.splice(3, 0, { - el: sortEntry - }); - Header.menu.addEntry({ - el: $.el('span', { - textContent: 'Index Navigation' - }), - order: 100, - subEntries: entries - }); - this.navLinks = $.el('div', { - className: 'navLinks json-index' - }); - $.extend(this.navLinks, {innerHTML: "Index Catalog Archive Bottom ×"}); - $('.cataloglink a', this.navLinks).href = CatalogLinks.catalog(); - if (!BoardConfig.isArchived(g.BOARD.ID)) { - $('.archlistlink', this.navLinks).hidden = true; - } - $.on($('#index-last-refresh a', this.navLinks), 'click', this.cb.refreshFront); - this.searchInput = $('#index-search', this.navLinks); - this.setupSearch(); - $.on(this.searchInput, 'input', this.onSearchInput); - $.on($('#index-search-clear', this.navLinks), 'click', this.clearSearch); - this.hideLabel = $('#hidden-label', this.navLinks); - $.on($('#hidden-toggle a', this.navLinks), 'click', this.cb.toggleHiddenThreads); - this.selectRev = $('#index-rev', this.navLinks); - this.selectMode = $('#index-mode', this.navLinks); - this.selectSort = $('#index-sort', this.navLinks); - this.selectSize = $('#index-size', this.navLinks); - $.on(this.selectRev, 'change', this.cb.sort); - $.on(this.selectMode, 'change', this.cb.mode); - $.on(this.selectSort, 'change', this.cb.sort); - $.on(this.selectSize, 'change', $.cb.value); - $.on(this.selectSize, 'change', this.cb.size); - ref5 = [this.selectMode, this.selectSize]; - for (k = 0, len1 = ref5.length; k < len1; k++) { - select = ref5[k]; - select.value = Conf[select.name]; - } - this.selectRev.checked = /-rev$/.test(Index.currentSort); - this.selectSort.value = Index.currentSort.replace(/-rev$/, ''); - this.lastLongOptions = $('#lastlong-options', this.navLinks); - this.lastLongInputs = $$('input', this.lastLongOptions); - this.lastLongThresholds = [0, 0]; - this.lastLongOptions.hidden = this.selectSort.value !== 'lastlong'; - ref6 = this.lastLongInputs; - for (i = l = 0, len2 = ref6.length; l < len2; i = ++l) { - input = ref6[i]; - $.on(input, 'change', this.cb.lastLongThresholds); - tRaw = Conf["Last Long Reply Thresholds " + i]; - input.value = this.lastLongThresholds[i] = typeof tRaw === 'object' ? (ref7 = tRaw[g.BOARD.ID]) != null ? ref7 : 100 : tRaw; - } - this.root = $.el('div', { - className: 'board json-index' - }); - $.on(this.root, 'click', this.cb.hoverToggle); - this.cb.size(); - this.cb.hover(); - this.pagelist = $.el('div', { - className: 'pagelist json-index' - }); - $.extend(this.pagelist, {innerHTML: "
    "}); - $('.cataloglink a', this.pagelist).href = CatalogLinks.catalog(); - $.on(this.pagelist, 'click', this.cb.pageNav); - this.update(true); - $.onExists(doc, 'title + *', function() { - return d.title = d.title.replace(/\ -\ Page\ \d+/, ''); - }); - $.onExists(doc, '.board > .thread > .postContainer, .board + *', function() { - var board, el, len3, m, ref8, timeEl, topNavPos; - g.SITE.Build.hat = $('.board > .thread > img:first-child'); - if (g.SITE.Build.hat) { - g.BOARD.threads.forEach(function(thread) { - if (thread.nodes.root) { - return $.prepend(thread.nodes.root, g.SITE.Build.hat.cloneNode(false)); - } - }); - $.addClass(doc, 'hats-enabled'); - $.addStyle(".catalog-thread::after {background-image: url(" + g.SITE.Build.hat.src + ");}"); - } - board = $('.board'); - $.replace(board, Index.root); - if (Index.loaded) { - $.event('PostsInserted', null, Index.root); - } - try { - d.implementation.createDocument(null, null, null).appendChild(board); - } catch (error) {} - ref8 = $$('.navLinks'); - for (m = 0, len3 = ref8.length; m < len3; m++) { - el = ref8[m]; - $.rm(el); - } - $.rm($.id('ctrl-top')); - topNavPos = $.id('delform').previousElementSibling; - $.before(topNavPos, $.el('hr')); - $.before(topNavPos, Index.navLinks); - timeEl = $('#index-last-refresh time', Index.navLinks); - if (timeEl.dataset.utc) { - return RelativeDates.update(timeEl); - } - }); - return Main.ready(function() { - var pagelist; - if ((pagelist = $('.pagelist'))) { - $.replace(pagelist, Index.pagelist); - } - return $.rmClass(doc, 'index-loading'); - }); - }, - scroll: function() { - var pageNum, threadIDs; - if (Index.req || !Index.liveThreadData || Conf['Index Mode'] !== 'infinite' || (window.scrollY <= doc.scrollHeight - (300 + window.innerHeight))) { - return; - } - if (Index.pageNum == null) { - Index.pageNum = Index.currentPage; - } - pageNum = ++Index.pageNum; - if (pageNum > Index.pagesNum) { - return Index.endNotice(); - } - threadIDs = Index.threadsOnPage(pageNum); - return Index.buildStructure(threadIDs); - }, - endNotice: (function() { - var notify, reset; - notify = false; - reset = function() { - return notify = false; - }; - return function() { - if (notify) { - return; - } - notify = true; - new Notice('info', "Last page reached.", 2); - return setTimeout(reset, 3 * $.SECOND); - }; - })(), - menu: { - init: function() { - if (!(g.VIEW === 'index' && Conf['Menu'] && Conf['Thread Hiding Link'] && Index.enabledOn(g.BOARD))) { - return; - } - return Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, {innerHTML: "Shift+click"}), - order: 20, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = thread.isHidden ? 'Unhide' : 'Hide'; - if (this.cb) { - $.off(this.el, 'click', this.cb); - } - this.cb = function() { - $.event('CloseMenu'); - return Index.toggleHide(thread); - }; - $.on(this.el, 'click', this.cb); - return true; - } - }); - } - }, - node: function() { - if (this.isReply || this.isClone || !(Index.threadPosition[this.ID] != null)) { - return; - } - return this.thread.setPage(Math.floor(Index.threadPosition[this.ID] / Index.threadsNumPerPage) + 1); - }, - catalogNode: function() { - return $.on(this.nodes.root, 'mousedown click', (function(_this) { - return function(e) { - if (!(e.button === 0 && e.shiftKey)) { - return; - } - if (e.type === 'click') { - Index.toggleHide(_this.thread); - } - return e.preventDefault(); - }; - })(this)); - }, - toggleHide: function(thread) { - if (Index.showHiddenThreads) { - ThreadHiding.show(thread); - if (!ThreadHiding.db.get({ - boardID: thread.board.ID, - threadID: thread.ID - })) { - return; - } - } else { - ThreadHiding.hide(thread); - } - return ThreadHiding.saveHiddenState(thread); - }, - cycleSortType: function() { - var i, k, len1, type, types; - types = slice.call(Index.selectSort.options).filter(function(option) { - return !option.disabled; - }); - for (i = k = 0, len1 = types.length; k < len1; i = ++k) { - type = types[i]; - if (type.selected) { - break; - } - } - types[(i + 1) % types.length].selected = true; - return $.event('change', null, Index.selectSort); - }, - cb: { - initFinished: function() { - Index.initFinishedFired = true; - return $.queueTask(function() { - return Index.cb.postsInserted(); - }); - }, - postsInserted: function() { - var n; - if (!Index.initFinishedFired) { - return; - } - n = 0; - g.posts.forEach(function(post) { - if (!post.isFetchedQuote && !post.indexRefreshSeen && doc.contains(post.nodes.root)) { - post.indexRefreshSeen = true; - return n++; - } - }); - if (n) { - return $.event('IndexRefresh'); - } - }, - toggleHiddenThreads: function() { - $('#hidden-toggle a', Index.navLinks).textContent = (Index.showHiddenThreads = !Index.showHiddenThreads) ? 'Hide' : 'Show'; - Index.sort(); - return Index.buildIndex(); - }, - mode: function() { - Index.pushState({ - mode: this.value - }); - return Index.pageLoad(false); - }, - sort: function() { - var value; - value = Index.selectRev.checked ? Index.selectSort.value + "-rev" : Index.selectSort.value; - Index.pushState({ - sort: value - }); - return Index.pageLoad(false); - }, - resort: function(e) { - var ref; - Index.changed.order = true; - if (!(e != null ? (ref = e.detail) != null ? ref.deferred : void 0 : void 0)) { - return Index.pageLoad(false); - } - }, - perBoardSort: function() { - var i, k; - Conf['Index Sort'] = this.checked ? $.dict() : ''; - Index.saveSort(); - for (i = k = 0; k < 2; i = ++k) { - Conf["Last Long Reply Thresholds " + i] = this.checked ? $.dict() : ''; - Index.saveLastLongThresholds(i); - } - }, - lastLongThresholds: function() { - var i, value; - i = slice.call(this.parentNode.children).indexOf(this); - value = +this.value; - if (!Number.isFinite(value)) { - this.value = Index.lastLongThresholds[i]; - return; - } - Index.lastLongThresholds[i] = value; - Index.saveLastLongThresholds(i); - Index.changed.order = true; - return Index.pageLoad(false); - }, - size: function(e) { - if (Conf['Index Mode'] !== 'catalog') { - $.rmClass(Index.root, 'catalog-small'); - $.rmClass(Index.root, 'catalog-large'); - } else if (Conf['Index Size'] === 'small') { - $.addClass(Index.root, 'catalog-small'); - $.rmClass(Index.root, 'catalog-large'); - } else { - $.addClass(Index.root, 'catalog-large'); - $.rmClass(Index.root, 'catalog-small'); - } - if (e) { - return Index.buildIndex(); - } - }, - replies: function() { - return Index.buildIndex(); - }, - hover: function() { - return doc.classList.toggle('catalog-hover-expand', Conf['Catalog Hover Expand']); - }, - hoverToggle: function(e) { - var input, thread; - if (Conf['Catalog Hover Toggle'] && $.hasClass(doc, 'catalog-mode') && !$.modifiedClick(e) && !$.x('ancestor-or-self::a', e.target)) { - input = Index.inputs['Catalog Hover Expand']; - input.checked = !input.checked; - $.event('change', null, input); - if ((thread = Get.threadFromNode(e.target))) { - Index.cb.catalogReplies.call(thread); - return Index.cb.hoverAdjust.call(thread.OP.nodes); - } - } - }, - popstate: function(e) { - var mode, nCommands, page, ref, searched, sort; - if (e != null ? e.state : void 0) { - ref = e.state, searched = ref.searched, mode = ref.mode, sort = ref.sort; - page = Index.getCurrentPage(); - Index.setState({ - search: searched, - mode: mode, - sort: sort, - page: page - }); - return Index.pageLoad(false); - } else { - nCommands = Index.processHash(); - if (Conf['Refreshed Navigation'] && nCommands) { - return Index.update(); - } else { - return Index.pageLoad(); - } - } - }, - pageNav: function(e) { - var a; - if ($.modifiedClick(e)) { - return; - } - switch (e.target.nodeName) { - case 'BUTTON': - e.target.blur(); - a = e.target.parentNode; - break; - case 'A': - a = e.target; - break; - default: - return; - } - if (a.textContent === 'Catalog') { - return; - } - e.preventDefault(); - return Index.userPageNav(+a.pathname.split(/\/+/)[2] || 1); - }, - refreshFront: function() { - Index.pushState({ - page: 1 - }); - return Index.update(); - }, - catalogReplies: function() { - if (Conf['Show Replies'] && $.hasClass(doc, 'catalog-hover-expand') && !this.catalogView.nodes.replies) { - return Index.buildCatalogReplies(this); - } - }, - hoverAdjust: function() { - var rect, style, x; - if (!$.hasClass(doc, 'catalog-hover-expand')) { - return; - } - rect = this.post.getBoundingClientRect(); - if ((x = $.minmax(0, -rect.left, doc.clientWidth - rect.right))) { - style = this.post.style; - style.left = x + "px"; - style.right = (-x) + "px"; - return $.one(this.root, 'mouseleave', function() { - return style.left = style.right = null; - }); - } - } - }, - scrollToIndex: function() { - return Header.scrollToIfNeeded((Index.navLinks.getBoundingClientRect().height ? Index.navLinks : Index.root)); - }, - getCurrentPage: function() { - return +window.location.pathname.split(/\/+/)[2] || 1; - }, - userPageNav: function(page) { - Index.pushState({ - page: page - }); - if (Conf['Refreshed Navigation']) { - return Index.update(); - } else { - return Index.pageLoad(); - } - }, - hashCommands: { - mode: { - 'paged': 'paged', - 'infinite-scrolling': 'infinite', - 'infinite': 'infinite', - 'all-threads': 'all pages', - 'all-pages': 'all pages', - 'catalog': 'catalog' - }, - sort: { - 'bump-order': 'bump', - 'last-reply': 'lastreply', - 'last-long-reply': 'lastlong', - 'creation-date': 'birth', - 'reply-count': 'replycount', - 'file-count': 'filecount', - 'posts-per-minute': 'activity' - } - }, - processHash: function() { - var command, commands, hash, k, leftover, len1, mode, ref, sort, state; - hash = ((ref = location.href.match(/#.*/)) != null ? ref[0] : void 0) || ''; - state = { - replace: true - }; - commands = hash.slice(1).split('/'); - leftover = []; - for (k = 0, len1 = commands.length; k < len1; k++) { - command = commands[k]; - if ((mode = $.getOwn(Index.hashCommands.mode, command))) { - state.mode = mode; - } else if (command === 'index') { - state.mode = Conf['Previous Index Mode']; - state.page = 1; - } else if ((sort = $.getOwn(Index.hashCommands.sort, command.replace(/-rev$/, '')))) { - state.sort = sort; - if (/-rev$/.test(command)) { - state.sort += '-rev'; - } - } else if (/^s=/.test(command)) { - state.search = decodeURIComponent(command.slice(2)).replace(/\+/g, ' ').trim(); - } else { - leftover.push(command); - } - } - hash = leftover.join('/'); - if (hash) { - state.hash = "#" + hash; - } - Index.pushState(state); - return commands.length - leftover.length; - }, - pushState: function(state) { - var hash, pageBeforeSearch, pathname, ref, replace, search; - search = state.search, hash = state.hash, replace = state.replace; - pageBeforeSearch = (ref = history.state) != null ? ref.oldpage : void 0; - if ((search != null) && search !== Index.search) { - state.page = search ? 1 : pageBeforeSearch || 1; - if (!search) { - pageBeforeSearch = void 0; - } else if (!Index.search) { - pageBeforeSearch = Index.currentPage; - } - } - Index.setState(state); - pathname = Index.currentPage === 1 ? "/" + g.BOARD + "/" : "/" + g.BOARD + "/" + Index.currentPage; - hash || (hash = ''); - return history[replace ? 'replaceState' : 'pushState']({ - mode: Conf['Index Mode'], - sort: Index.currentSort, - searched: Index.search, - oldpage: pageBeforeSearch - }, '', location.protocol + "//" + location.host + pathname + hash); - }, - setState: function(arg) { - var hash, mode, page, ref, search, sort; - search = arg.search, mode = arg.mode, sort = arg.sort, page = arg.page, hash = arg.hash; - if ((search != null) && search !== Index.search) { - Index.changed.search = true; - Index.search = search; - } - if ((mode != null) && mode !== Conf['Index Mode']) { - Index.changed.mode = true; - Conf['Index Mode'] = mode; - $.set('Index Mode', mode); - if (!(mode === 'catalog' || Conf['Previous Index Mode'] === mode)) { - Conf['Previous Index Mode'] = mode; - $.set('Previous Index Mode', mode); - } - } - if ((sort != null) && sort !== Index.currentSort) { - Index.changed.sort = true; - Index.currentSort = sort; - Index.saveSort(); - } - if ((ref = Conf['Index Mode']) === 'all pages' || ref === 'catalog') { - page = 1; - } - if ((page != null) && page !== Index.currentPage) { - Index.changed.page = true; - Index.currentPage = page; - } - if (hash != null) { - return Index.changed.hash = true; - } - }, - savePerBoard: function(key, value) { - if (typeof Conf[key] === 'object') { - Conf[key][g.BOARD.ID] = value; - } else { - Conf[key] = value; - } - return $.set(key, Conf[key]); - }, - saveSort: function() { - return Index.savePerBoard('Index Sort', Index.currentSort); - }, - saveLastLongThresholds: function(i) { - return Index.savePerBoard("Last Long Reply Thresholds " + i, Index.lastLongThresholds[i]); - }, - pageLoad: function(scroll) { - var hash, mode, order, page, ref, search, sort, threads; - if (scroll == null) { - scroll = true; - } - if (!Index.liveThreadData) { - return; - } - ref = Index.changed, threads = ref.threads, order = ref.order, search = ref.search, mode = ref.mode, sort = ref.sort, page = ref.page, hash = ref.hash; - threads || (threads = search); - order || (order = sort); - if (threads || order) { - Index.sort(); - } - if (threads) { - Index.buildPagelist(); - } - if (search) { - Index.setupSearch(); - } - if (mode) { - Index.setupMode(); - } - if (sort) { - Index.setupSort(); - } - if (threads || mode || page || order) { - Index.buildIndex(); - } - if (threads || page) { - Index.setPage(); - } - if (scroll && !hash) { - Index.scrollToIndex(); - } - if (hash) { - Header.hashScroll(); - } - return Index.changed = {}; - }, - setupMode: function() { - var k, len1, mode, ref; - ref = ['paged', 'infinite', 'all pages', 'catalog']; - for (k = 0, len1 = ref.length; k < len1; k++) { - mode = ref[k]; - $[mode === Conf['Index Mode'] ? 'addClass' : 'rmClass'](doc, (mode.replace(/\ /g, '-')) + "-mode"); - } - Index.selectMode.value = Conf['Index Mode']; - Index.cb.size(); - Index.showHiddenThreads = false; - return $('#hidden-toggle a', Index.navLinks).textContent = 'Show'; - }, - setupSort: function() { - Index.selectRev.checked = /-rev$/.test(Index.currentSort); - Index.selectSort.value = Index.currentSort.replace(/-rev$/, ''); - return Index.lastLongOptions.hidden = Index.selectSort.value !== 'lastlong'; - }, - getPagesNum: function() { - if (Index.search) { - return Math.ceil(Index.sortedThreadIDs.length / Index.threadsNumPerPage); - } else { - return Index.pagesNum; - } - }, - getMaxPageNum: function() { - return Math.max(1, Index.getPagesNum()); - }, - buildPagelist: function() { - var a, i, k, maxPageNum, nodes, pagesRoot, ref; - pagesRoot = $('.pages', Index.pagelist); - maxPageNum = Index.getMaxPageNum(); - if (pagesRoot.childElementCount !== maxPageNum) { - nodes = []; - for (i = k = 1, ref = maxPageNum; k <= ref; i = k += 1) { - a = $.el('a', { - textContent: i, - href: i === 1 ? './' : i - }); - nodes.push($.tn('['), a, $.tn('] ')); - } - $.rmAll(pagesRoot); - return $.add(pagesRoot, nodes); - } - }, - setPage: function() { - var a, href, maxPageNum, next, pageNum, pagesRoot, prev, strong; - pageNum = Index.currentPage; - maxPageNum = Index.getMaxPageNum(); - pagesRoot = $('.pages', Index.pagelist); - prev = pagesRoot.previousSibling.firstChild; - next = pagesRoot.nextSibling.firstChild; - href = Math.max(pageNum - 1, 1); - prev.href = href === 1 ? './' : href; - prev.firstChild.disabled = href === pageNum; - href = Math.min(pageNum + 1, maxPageNum); - next.href = href === 1 ? './' : href; - next.firstChild.disabled = href === pageNum; - if (strong = $('strong', pagesRoot)) { - if (+strong.textContent === pageNum) { - return; - } - $.replace(strong, strong.firstChild); - } else { - strong = $.el('strong'); - } - if ((a = pagesRoot.children[pageNum - 1])) { - $.before(a, strong); - return $.add(strong, a); - } - }, - updateHideLabel: function() { - var hiddenCount, k, len1, ref, threadID; - if (!Index.hideLabel) { - return; - } - hiddenCount = 0; - ref = Index.liveThreadIDs; - for (k = 0, len1 = ref.length; k < len1; k++) { - threadID = ref[k]; - if (Index.isHidden(threadID)) { - hiddenCount++; - } - } - if (!hiddenCount) { - Index.hideLabel.hidden = true; - if (Index.showHiddenThreads) { - Index.cb.toggleHiddenThreads(); - } - return; - } - Index.hideLabel.hidden = false; - return $('#hidden-count', Index.navLinks).textContent = hiddenCount === 1 ? '1 hidden thread' : hiddenCount + " hidden threads"; - }, - update: function(firstTime) { - var oldReq; - if ((oldReq = Index.req)) { - delete Index.req; - oldReq.abort(); - } - if (Conf['Index Refresh Notifications']) { - Index.notice || (Index.notice = new Notice('info', 'Refreshing index...')); - Index.nTimeout || (Index.nTimeout = setTimeout(function() { - var ref; - return (ref = Index.notice) != null ? ref.el.lastElementChild.textContent += ' (disable JSON Index if this takes too long)' : void 0; - }, 3 * $.SECOND)); - } else { - Index.nTimeout || (Index.nTimeout = setTimeout(function() { - return Index.notice || (Index.notice = new Notice('info', 'Refreshing index... (disable JSON Index if this takes too long)')); - }, 3 * $.SECOND)); - } - if (!firstTime && d.readyState !== 'loading' && !$('.board + *')) { - location.reload(); - return; - } - Index.req = $.whenModified(g.SITE.urls.catalogJSON({ - boardID: g.BOARD.ID - }), 'Index', Index.load); - return $.addClass(Index.button, 'fa-spin'); - }, - load: function() { - var err, nTimeout, notice, ref, timeEl; - if (this !== Index.req) { - return; - } - $.rmClass(Index.button, 'fa-spin'); - notice = Index.notice, nTimeout = Index.nTimeout; - if (nTimeout) { - clearTimeout(nTimeout); - } - delete Index.nTimeout; - delete Index.req; - delete Index.notice; - if ((ref = this.status) !== 200 && ref !== 304) { - err = "Index refresh failed. " + (this.status ? "Error " + this.statusText + " (" + this.status + ")" : 'Connection Error'); - if (notice) { - notice.setType('warning'); - notice.el.lastElementChild.textContent = err; - setTimeout(notice.close, $.SECOND); - } else { - new Notice('warning', err, 1); - } - return; - } - try { - if (this.status === 200) { - Index.parse(this.response); - } else if (this.status === 304) { - Index.pageLoad(); - } - } catch (error) { - err = error; - c.error("Index failure: " + err.message, err.stack); - if (notice) { - notice.setType('error'); - notice.el.lastElementChild.textContent = 'Index refresh failed.'; - setTimeout(notice.close, $.SECOND); - } else { - new Notice('error', 'Index refresh failed.', 1); - } - return; - } - if (notice) { - if (Conf['Index Refresh Notifications']) { - notice.setType('success'); - notice.el.lastElementChild.textContent = 'Index refreshed!'; - setTimeout(notice.close, $.SECOND); - } else { - notice.close(); - } - } - timeEl = $('#index-last-refresh time', Index.navLinks); - timeEl.dataset.utc = Date.parse(this.getResponseHeader('Last-Modified')); - return RelativeDates.update(timeEl); - }, - parse: function(pages) { - $.cleanCache(function(url) { - return /^https?:\/\/a\.4cdn\.org\//.test(url); - }); - Index.parseThreadList(pages); - Index.changed.threads = true; - return Index.pageLoad(); - }, - parseThreadList: function(pages) { - var ID, data, i, k, l, len1, len2, obj, ref, ref1, ref2, reply, results; - Index.pagesNum = pages.length; - Index.threadsNumPerPage = ((ref = pages[0]) != null ? ref.threads.length : void 0) || 1; - Index.liveThreadData = pages.reduce((function(arr, next) { - return arr.concat(next.threads); - }), []); - Index.liveThreadIDs = Index.liveThreadData.map(function(data) { - return data.no; - }); - Index.liveThreadDict = $.dict(); - Index.threadPosition = $.dict(); - Index.parsedThreads = $.dict(); - Index.replyData = $.dict(); - ref1 = Index.liveThreadData; - for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { - data = ref1[i]; - Index.liveThreadDict[data.no] = data; - Index.threadPosition[data.no] = i; - Index.parsedThreads[data.no] = obj = g.SITE.Build.parseJSON(data, g.BOARD); - obj.filterResults = results = Filter.test(obj); - obj.isOnTop = results.top; - obj.isHidden = results.hide || ThreadHiding.isHidden(obj.boardID, obj.threadID); - if (data.last_replies) { - ref2 = data.last_replies; - for (l = 0, len2 = ref2.length; l < len2; l++) { - reply = ref2[l]; - Index.replyData[g.BOARD + "." + reply.no] = reply; - } - } - } - if (Index.liveThreadData[0]) { - g.SITE.Build.spoilerRange[g.BOARD.ID] = Index.liveThreadData[0].custom_spoiler; - } - g.BOARD.threads.forEach(function(thread) { - var ref3; - if (ref3 = thread.ID, indexOf.call(Index.liveThreadIDs, ref3) < 0) { - return thread.collect(); - } - }); - $.event('IndexUpdate', { - threads: (function() { - var len3, m, ref3, results1; - ref3 = Index.liveThreadIDs; - results1 = []; - for (m = 0, len3 = ref3.length; m < len3; m++) { - ID = ref3[m]; - results1.push(g.BOARD + "." + ID); - } - return results1; - })() - }); - }, - isHidden: function(threadID) { - var thread; - if ((thread = g.BOARD.threads.get(threadID)) && thread.OP && !thread.OP.isFetchedQuote) { - return thread.isHidden; - } else { - return Index.parsedThreads[threadID].isHidden; - } - }, - isHiddenReply: function(threadID, replyData) { - return PostHiding.isHidden(g.BOARD.ID, threadID, replyData.no) || Filter.isHidden(g.SITE.Build.parseJSON(replyData, g.BOARD)); - }, - buildThreads: function(threadIDs, isCatalog, withReplies) { - var ID, OP, err, errors, isStale, k, lastPost, len1, newPosts, newThreads, obj, opRoot, t, thread, threadData, threads; - threads = []; - newThreads = []; - newPosts = []; - for (k = 0, len1 = threadIDs.length; k < len1; k++) { - ID = threadIDs[k]; - try { - threadData = Index.liveThreadDict[ID]; - if ((thread = g.BOARD.threads.get(ID))) { - isStale = (thread.json !== threadData) && (JSON.stringify(thread.json) !== JSON.stringify(threadData)); - if (isStale) { - thread.setCount('post', threadData.replies + 1, threadData.bumplimit); - thread.setCount('file', threadData.images + !!threadData.ext, threadData.imagelimit); - thread.setStatus('Sticky', !!threadData.sticky); - thread.setStatus('Closed', !!threadData.closed); - } - if (thread.catalogView) { - $.rm(thread.catalogView.nodes.replies); - thread.catalogView.nodes.replies = null; - } - } else { - thread = new Thread(ID, g.BOARD); - newThreads.push(thread); - } - lastPost = threadData.last_replies && threadData.last_replies.length ? threadData.last_replies[threadData.last_replies.length - 1].no : ID; - if (lastPost > thread.lastPost) { - thread.lastPost = lastPost; - } - thread.json = threadData; - threads.push(thread); - if ((OP = thread.OP) && !OP.isFetchedQuote) { - OP.setCatalogOP(isCatalog); - thread.setPage(Math.floor(Index.threadPosition[ID] / Index.threadsNumPerPage) + 1); - } else { - obj = Index.parsedThreads[ID]; - opRoot = g.SITE.Build.post(obj); - OP = new Post(opRoot, thread, g.BOARD); - OP.filterResults = obj.filterResults; - newPosts.push(OP); - } - if (!(isCatalog && thread.nodes.root)) { - g.SITE.Build.thread(thread, threadData, withReplies); - } - } catch (error) { - err = error; - if (!errors) { - errors = []; - } - errors.push({ - message: "Parsing of Thread No." + thread + " failed. Thread will be skipped.", - error: err, - html: opRoot != null ? opRoot.outerHTML : void 0 - }); - } - } - if (errors) { - Main.handleErrors(errors); - } - if (withReplies) { - newPosts = newPosts.concat(Index.buildReplies(threads)); - } - Main.callbackNodes('Thread', newThreads); - Main.callbackNodes('Post', newPosts); - Index.updateHideLabel(); - $.event('IndexRefreshInternal', { - threadIDs: (function() { - var l, len2, results1; - results1 = []; - for (l = 0, len2 = threads.length; l < len2; l++) { - t = threads[l]; - results1.push(t.fullID); - } - return results1; - })(), - isCatalog: isCatalog - }); - return threads; - }, - buildReplies: function(threads) { - var data, err, errors, k, l, lastReplies, len1, len2, node, nodes, post, posts, thread; - posts = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - if (!(lastReplies = Index.liveThreadDict[thread.ID].last_replies)) { - continue; - } - nodes = []; - for (l = 0, len2 = lastReplies.length; l < len2; l++) { - data = lastReplies[l]; - if ((post = thread.posts.get(data.no)) && !post.isFetchedQuote) { - nodes.push(post.nodes.root); - continue; - } - nodes.push(node = g.SITE.Build.postFromObject(data, thread.board.ID)); - try { - posts.push(new Post(node, thread, thread.board)); - } catch (error) { - err = error; - if (!errors) { - errors = []; - } - errors.push({ - message: "Parsing of Post No." + data.no + " failed. Post will be skipped.", - error: err, - html: node != null ? node.outerHTML : void 0 - }); - } - } - $.add(thread.nodes.root, nodes); - } - if (errors) { - Main.handleErrors(errors); - } - return posts; - }, - buildCatalogViews: function(threads) { - var ID, catalogThreads, k, len1, page, root, thread; - catalogThreads = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - if (!(!thread.catalogView)) { - continue; - } - ID = thread.ID; - page = Math.floor(Index.threadPosition[ID] / Index.threadsNumPerPage) + 1; - root = g.SITE.Build.catalogThread(thread, Index.liveThreadDict[ID], page); - catalogThreads.push(new CatalogThread(root, thread)); - } - Main.callbackNodes('CatalogThread', catalogThreads); - }, - sizeCatalogViews: function(threads) { - var height, k, len1, ratio, ref, size, thread, thumb, width; - size = Conf['Index Size'] === 'small' ? 150 : 250; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - thumb = thread.catalogView.nodes.thumb; - ref = thumb.dataset, width = ref.width, height = ref.height; - if (!width) { - continue; - } - ratio = size / Math.max(width, height); - thumb.style.width = width * ratio + 'px'; - thumb.style.height = height * ratio + 'px'; - } - }, - buildCatalogReplies: function(thread) { - var data, k, lastReplies, len1, nodes, replies, reply; - nodes = thread.catalogView.nodes; - if (!(lastReplies = Index.liveThreadDict[thread.ID].last_replies)) { - return; - } - replies = []; - for (k = 0, len1 = lastReplies.length; k < len1; k++) { - data = lastReplies[k]; - if (Index.isHiddenReply(thread.ID, data)) { - continue; - } - reply = g.SITE.Build.catalogReply(thread, data); - RelativeDates.update($('time', reply)); - $.on($('.catalog-reply-preview', reply), 'mouseover', QuotePreview.mouseover); - replies.push(reply); - } - nodes.replies = $.el('div', { - className: 'catalog-replies' - }); - $.add(nodes.replies, replies); - $.add(thread.OP.nodes.post, nodes.replies); - }, - sort: function() { - var lastlong, lastlongD, liveThreadData, liveThreadIDs, repliesAvailable, sortType, thread, threadIDs, tmp_time; - liveThreadIDs = Index.liveThreadIDs, liveThreadData = Index.liveThreadData; - if (!liveThreadData) { - return; - } - tmp_time = new Date().getTime() / 1000; - sortType = Index.currentSort.replace(/-rev$/, ''); - Index.sortedThreadIDs = (function() { - var k, len1; - switch (sortType) { - case 'lastreply': - case 'lastlong': - repliesAvailable = liveThreadData.some(function(thread) { - var ref; - return (ref = thread.last_replies) != null ? ref.length : void 0; - }); - lastlong = function(thread) { - var i, k, len, r, ref, ref1; - if (!repliesAvailable) { - return thread.last_modified; - } - ref = thread.last_replies || []; - for (i = k = ref.length - 1; k >= 0; i = k += -1) { - r = ref[i]; - if (Index.isHiddenReply(thread.no, r)) { - continue; - } - if (sortType === 'lastreply') { - return r; - } - len = r.com ? g.SITE.Build.parseComment(r.com).replace(/[^a-z]/ig, '').length : 0; - if (len >= Index.lastLongThresholds[+(!!r.ext)]) { - return r; - } - } - if (thread.omitted_posts && ((ref1 = thread.last_replies) != null ? ref1.length : void 0)) { - return thread.last_replies[0]; - } else { - return thread; - } - }; - lastlongD = $.dict(); - for (k = 0, len1 = liveThreadData.length; k < len1; k++) { - thread = liveThreadData[k]; - lastlongD[thread.no] = lastlong(thread).no; - } - return slice.call(liveThreadData).sort(function(a, b) { - return lastlongD[b.no] - lastlongD[a.no]; - }).map(function(post) { - return post.no; - }); - case 'bump': - return liveThreadIDs; - case 'birth': - return slice.call(liveThreadIDs).sort(function(a, b) { - return b - a; - }); - case 'replycount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.replies - a.replies; - }).map(function(post) { - return post.no; - }); - case 'filecount': - return slice.call(liveThreadData).sort(function(a, b) { - return b.images - a.images; - }).map(function(post) { - return post.no; - }); - case 'activity': - return slice.call(liveThreadData).sort(function(a, b) { - return (tmp_time - a.time) / (a.replies + 1) - (tmp_time - b.time) / (b.replies + 1); - }).map(function(post) { - return post.no; - }); - default: - return liveThreadIDs; - } - })(); - if (/-rev$/.test(Index.currentSort)) { - Index.sortedThreadIDs = slice.call(Index.sortedThreadIDs).reverse(); - } - if (Index.search && (threadIDs = Index.querySearch(Index.search))) { - Index.sortedThreadIDs = threadIDs; - } - Index.sortOnTop(function(obj) { - return obj.isSticky; - }); - Index.sortOnTop(function(obj) { - return obj.isOnTop || Conf['Pin Watched Threads'] && ThreadWatcher.isWatchedRaw(obj.boardID, obj.threadID); - }); - if (Conf['Anchor Hidden Threads']) { - return Index.sortOnTop(function(obj) { - return !Index.isHidden(obj.threadID); - }); - } - }, - sortOnTop: function(match) { - var ID, bottomThreads, k, len1, ref, topThreads; - topThreads = []; - bottomThreads = []; - ref = Index.sortedThreadIDs; - for (k = 0, len1 = ref.length; k < len1; k++) { - ID = ref[k]; - (match(Index.parsedThreads[ID]) ? topThreads : bottomThreads).push(ID); - } - return Index.sortedThreadIDs = topThreads.concat(bottomThreads); - }, - buildIndex: function() { - var threadIDs; - if (!Index.liveThreadData) { - return; - } - switch (Conf['Index Mode']) { - case 'all pages': - threadIDs = Index.sortedThreadIDs; - break; - case 'catalog': - threadIDs = Index.sortedThreadIDs.filter(function(ID) { - return !Index.isHidden(ID) !== Index.showHiddenThreads; - }); - break; - default: - threadIDs = Index.threadsOnPage(Index.currentPage); - } - delete Index.pageNum; - $.rmAll(Index.root); - $.rmAll(Header.hover); - if (Index.loaded && Index.root.parentNode) { - $.event('PostsRemoved', null, Index.root); - } - if (Conf['Index Mode'] === 'catalog') { - Index.buildCatalog(threadIDs); - } else { - Index.buildStructure(threadIDs); - } - }, - threadsOnPage: function(pageNum) { - var nodesPerPage, offset; - nodesPerPage = Index.threadsNumPerPage; - offset = nodesPerPage * (pageNum - 1); - return Index.sortedThreadIDs.slice(offset, offset + nodesPerPage); - }, - buildStructure: function(threadIDs) { - var k, len1, nodes, thread, threads; - threads = Index.buildThreads(threadIDs, false, Conf['Show Replies']); - nodes = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - nodes.push(thread.nodes.root, $.el('hr')); - } - $.add(Index.root, nodes); - if (Index.root.parentNode) { - $.event('PostsInserted', null, Index.root); - } - Index.loaded = true; - }, - buildCatalog: function(threadIDs) { - var fn, i, n, node0; - i = 0; - n = threadIDs.length; - node0 = null; - fn = function() { - var j; - if (node0 && !node0.parentNode) { - return; - } - j = i > 0 && Index.root.parentNode ? n : i + 30; - node0 = Index.buildCatalogPart(threadIDs.slice(i, j))[0]; - i = j; - if (i < n) { - return $.queueTask(fn); - } else { - if (Index.root.parentNode) { - $.event('PostsInserted', null, Index.root); - } - return Index.loaded = true; - } - }; - fn(); - }, - buildCatalogPart: function(threadIDs) { - var k, len1, nodes, thread, threads; - threads = Index.buildThreads(threadIDs, true); - Index.buildCatalogViews(threads); - Index.sizeCatalogViews(threads); - nodes = []; - for (k = 0, len1 = threads.length; k < len1; k++) { - thread = threads[k]; - thread.OP.setCatalogOP(true); - $.add(thread.catalogView.nodes.root, thread.OP.nodes.root); - nodes.push(thread.catalogView.nodes.root); - $.on(thread.catalogView.nodes.root, 'mouseenter', Index.cb.catalogReplies.bind(thread)); - $.on(thread.OP.nodes.root, 'mouseenter', Index.cb.hoverAdjust.bind(thread.OP.nodes)); - } - $.add(Index.root, nodes); - return nodes; - }, - clearSearch: function() { - Index.searchInput.value = ''; - Index.onSearchInput(); - return Index.searchInput.focus(); - }, - setupSearch: function() { - Index.searchInput.value = Index.search; - if (Index.search) { - return Index.searchInput.dataset.searching = 1; - } else { - return Index.searchInput.removeAttribute('data-searching'); - } - }, - onSearchInput: function() { - var search; - search = Index.searchInput.value.trim(); - if (search === Index.search) { - return; - } - Index.pushState({ - search: search, - replace: !!search === !!Index.search - }); - return Index.pageLoad(false); - }, - querySearch: function(query) { - var keywords, match, regexp; - if ((match = query.match(/^([\w+]+):\/(.*)\/(\w*)$/))) { - try { - regexp = RegExp(match[2], match[3]); - } catch (error) { - return []; - } - return Index.sortedThreadIDs.filter(function(ID) { - return regexp.test(Filter.values(match[1], Index.parsedThreads[ID]).join('\n')); - }); - } - if (!(keywords = query.toLowerCase().match(/\S+/g))) { - return; - } - return Index.sortedThreadIDs.filter(function(ID) { - return Index.searchMatch(Index.parsedThreads[ID], keywords); - }); - }, - searchMatch: function(obj, keywords) { - var file, info, k, key, keyword, l, len1, len2, ref, text; - info = obj.info, file = obj.file; - if (info.comment == null) { - info.comment = g.SITE.Build.parseComment(info.commentHTML.innerHTML); - } - text = []; - ref = ['comment', 'subject', 'name', 'tripcode']; - for (k = 0, len1 = ref.length; k < len1; k++) { - key = ref[k]; - if (key in info) { - text.push(info[key]); - } - } - if (file) { - text.push(file.name); - } - text = text.join(' ').toLowerCase(); - for (l = 0, len2 = keywords.length; l < len2; l++) { - keyword = keywords[l]; - if (-1 === text.indexOf(keyword)) { - return false; - } - } - return true; - } - }; - - return Index; - -}).call(this); - -Polyfill = (function() { - var Polyfill; - - Polyfill = { - init: function() { - var base; - this.toBlob(); - $.global(this.toBlob); - (base = Element.prototype).matches || (base.matches = Element.prototype.mozMatchesSelector || Element.prototype.webkitMatchesSelector); - }, - toBlob: function() { - if (HTMLCanvasElement.prototype.toBlob) { - return; - } - HTMLCanvasElement.prototype.toBlob = function(cb, type, encoderOptions) { - var data, i, j, l, ref, ui8a, url; - url = this.toDataURL(type, encoderOptions); - data = atob(url.slice(url.indexOf(',') + 1)); - l = data.length; - ui8a = new Uint8Array(l); - for (i = j = 0, ref = l; j < ref; i = j += 1) { - ui8a[i] = data.charCodeAt(i); - } - return cb(new Blob([ui8a], { - type: type || 'image/png' - })); - }; - } - }; - - return Polyfill; - -}).call(this); - -Settings = (function() { - var Settings, - slice = [].slice, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Settings = { - init: function() { - var add, link; - link = $.el('a', { - className: 'settings-link fa fa-wrench', - textContent: 'Settings', - title: '4chan X Settings', - href: 'javascript:;' - }); - $.on(link, 'click', Settings.open); - Header.addShortcut('settings', link, 820); - add = this.addSection; - add('Main', this.main); - add('Filter', this.filter); - add('Sauce', this.sauce); - add('Advanced', this.advanced); - add('Keybinds', this.keybinds); - $.on(d, 'AddSettingsSection', Settings.addSection); - $.on(d, 'OpenSettings', function(e) { - return Settings.open(e.detail); - }); - if (g.SITE.software === 'yotsuba' && Conf['Disable Native Extension']) { - if ($.hasStorage) { - return $.global(function() { - var settings; - try { - settings = JSON.parse(localStorage.getItem('4chan-settings')) || {}; - if (settings.disableAll) { - return; - } - settings.disableAll = true; - return localStorage.setItem('4chan-settings', JSON.stringify(settings)); - } catch (error) { - return Object.defineProperty(window, 'Config', { - value: { - disableAll: true - } - }); - } - }); - } else { - return $.global(function() { - return Object.defineProperty(window, 'Config', { - value: { - disableAll: true - } - }); - }); - } - } - }, - open: function(openSection) { - var dialog, j, len, link, links, ref, section, sectionToOpen; - if (Settings.dialog) { - return; - } - $.event('CloseMenu'); - Settings.dialog = dialog = $.el('div', { - id: 'overlay' - }, {innerHTML: ""}); - $.on($('.export', dialog), 'click', Settings["export"]); - $.on($('.import', dialog), 'click', Settings["import"]); - $.on($('.reset', dialog), 'click', Settings.reset); - $.on($('input', dialog), 'change', Settings.onImport); - links = []; - ref = Settings.sections; - for (j = 0, len = ref.length; j < len; j++) { - section = ref[j]; - link = $.el('a', { - className: "tab-" + section.hyphenatedTitle, - textContent: section.title, - href: 'javascript:;' - }); - $.on(link, 'click', Settings.openSection.bind(section)); - links.push(link, $.tn(' | ')); - if (section.title === openSection) { - sectionToOpen = link; - } - } - links.pop(); - $.add($('.sections-list', dialog), links); - if (openSection !== 'none') { - (sectionToOpen ? sectionToOpen : links[0]).click(); - } - $.on($('.close', dialog), 'click', Settings.close); - $.on(window, 'beforeunload', Settings.close); - $.on(dialog, 'click', Settings.close); - $.on(dialog.firstElementChild, 'click', function(e) { - return e.stopPropagation(); - }); - $.add(d.body, dialog); - return $.event('OpenSettings', null, dialog); - }, - close: function() { - var ref; - if (!Settings.dialog) { - return; - } - if ((ref = d.activeElement) != null) { - ref.blur(); - } - $.rm(Settings.dialog); - return delete Settings.dialog; - }, - sections: [], - addSection: function(title, open) { - var hyphenatedTitle, ref; - if (typeof title !== 'string') { - ref = title.detail, title = ref.title, open = ref.open; - } - hyphenatedTitle = title.toLowerCase().replace(/\s+/g, '-'); - return Settings.sections.push({ - title: title, - hyphenatedTitle: hyphenatedTitle, - open: open - }); - }, - openSection: function() { - var section, selected; - if (selected = $('.tab-selected', Settings.dialog)) { - $.rmClass(selected, 'tab-selected'); - } - $.addClass($(".tab-" + this.hyphenatedTitle, Settings.dialog), 'tab-selected'); - section = $('section', Settings.dialog); - $.rmAll(section); - section.className = "section-" + this.hyphenatedTitle; - this.open(section, g); - section.scrollTop = 0; - return $.event('OpenSettings', null, section); - }, - warnings: { - localStorage: function(cb) { - var why; - if ($.cantSync) { - why = $.cantSet ? 'save your settings' : 'synchronize settings between tabs'; - return cb($.el('li', { - textContent: "4chan X needs local storage to " + why + ".\nEnable it on boards." + (location.hostname.split('.')[1]) + ".org in your browser's privacy settings (may be listed as part of \"local data\" or \"cookies\")." - })); - } - }, - ads: function(cb) { - return $.onExists(doc, '.adg-rects > .desktop', function(ad) { - return $.onExists(ad, 'iframe', function() { - var url; - url = Redirect.to('thread', { - boardID: 'qa', - threadID: 362590 - }); - return cb($.el('li', {innerHTML: "To protect yourself from malicious ads, you should block ads on 4chan."})); - }); - }); - } - }, - main: function(section) { - var addCheckboxes, addWarning, button, div, fs, inputs, items, key, keyFS, obj, ref, ref1, warning, warnings; - warnings = $.el('fieldset', { - hidden: true - }, {innerHTML: "Warnings
      "}); - addWarning = function(item) { - $.add($('ul', warnings), item); - return warnings.hidden = false; - }; - ref = Settings.warnings; - for (key in ref) { - warning = ref[key]; - warning(addWarning); - } - $.add(section, warnings); - items = $.dict(); - inputs = $.dict(); - addCheckboxes = function(root, obj) { - var arr, container, containers, description, div, input, level, results; - containers = [root]; - results = []; - for (key in obj) { - arr = obj[key]; - if (!(arr instanceof Array)) { - continue; - } - description = arr[1]; - div = $.el('div', {innerHTML: ": " + E(description) + ""}); - div.dataset.name = key; - input = $('input', div); - $.on(input, 'change', $.cb.checked); - $.on(input, 'change', function() { - return this.parentNode.parentNode.dataset.checked = this.checked; - }); - items[key] = Conf[key]; - inputs[key] = input; - level = arr[2] || 0; - if (containers.length <= level) { - container = $.el('div', { - className: 'suboption-list' - }); - $.add(containers[containers.length - 1].lastElementChild, container); - containers[level] = container; - } else if (containers.length > level + 1) { - containers.splice(level + 1, containers.length - (level + 1)); - } - results.push($.add(containers[level], div)); - } - return results; - }; - ref1 = Config.main; - for (keyFS in ref1) { - obj = ref1[keyFS]; - fs = $.el('fieldset', {innerHTML: "" + E(keyFS) + ""}); - addCheckboxes(fs, obj); - if (keyFS === 'Posting and Captchas') { - $.add(fs, $.el('p', {innerHTML: "For more info on captcha options and issues, see the captcha FAQ."})); - } - $.add(section, fs); - } - addCheckboxes($('div[data-name="JSON Index"] > .suboption-list', section), Config.Index); - if ($.engine !== 'gecko') { - $('div[data-name="Remember QR Size"]', section).hidden = true; - } - if ($.perProtocolSettings || location.protocol !== 'https:') { - $('div[data-name="Redirect to HTTPS"]', section).hidden = true; - } - if ($.platform !== 'crx') { - $('div[data-name="Work around CORB Bug"]', section).hidden = true; - } - $.get(items, function(items) { - var val; - for (key in items) { - val = items[key]; - inputs[key].checked = val; - inputs[key].parentNode.parentNode.dataset.checked = val; - } - }); - div = $.el('div', {innerHTML: ": Clear manually-hidden threads and posts on all boards. Reload the page to apply."}); - button = $('button', div); - $.get({ - hiddenThreads: $.dict(), - hiddenPosts: $.dict() - }, function(arg) { - var ID, board, hiddenNum, hiddenPosts, hiddenThreads, ref2, ref3, ref4, ref5, site, thread; - hiddenThreads = arg.hiddenThreads, hiddenPosts = arg.hiddenPosts; - hiddenNum = 0; - for (ID in hiddenThreads) { - site = hiddenThreads[ID]; - if (ID !== 'boards') { - ref2 = site.boards; - for (ID in ref2) { - board = ref2[ID]; - hiddenNum += Object.keys(board).length; - } - } - } - ref3 = hiddenThreads.boards; - for (ID in ref3) { - board = ref3[ID]; - hiddenNum += Object.keys(board).length; - } - for (ID in hiddenPosts) { - site = hiddenPosts[ID]; - if (ID !== 'boards') { - ref4 = site.boards; - for (ID in ref4) { - board = ref4[ID]; - for (ID in board) { - thread = board[ID]; - hiddenNum += Object.keys(thread).length; - } - } - } - } - ref5 = hiddenPosts.boards; - for (ID in ref5) { - board = ref5[ID]; - for (ID in board) { - thread = board[ID]; - hiddenNum += Object.keys(thread).length; - } - } - return button.textContent = "Hidden: " + hiddenNum; - }); - $.on(button, 'click', function() { - this.textContent = 'Hidden: 0'; - return $.get('hiddenThreads', $.dict(), function(arg) { - var boardID, hiddenThreads, ref2; - hiddenThreads = arg.hiddenThreads; - if ($.hasStorage && g.SITE.software === 'yotsuba') { - for (boardID in (ref2 = hiddenThreads['4chan.org']) != null ? ref2.boards : void 0) { - localStorage.removeItem("4chan-hide-t-" + boardID); - } - for (boardID in hiddenThreads.boards) { - localStorage.removeItem("4chan-hide-t-" + boardID); - } - } - return $["delete"](['hiddenThreads', 'hiddenPosts']); - }); - }); - return $.after($('input[name="Stubs"]', section).parentNode.parentNode, div); - }, - "export": function() { - var Conf2; - Conf2 = $.dict(); - $.extend(Conf2, Conf); - return $.get(Conf2, function(Conf2) { - delete Conf2['boardConfig']; - return Settings.downloadExport({ - version: g.VERSION, - date: Date.now(), - Conf: Conf2 - }); - }); - }, - downloadExport: function(data) { - var a, blob, p, url; - blob = new Blob([JSON.stringify(data, null, 2)], { - type: 'application/json' - }); - url = URL.createObjectURL(blob); - a = $.el('a', { - download: "4chan X v" + g.VERSION + "-" + data.date + ".json", - href: url - }); - p = $('.imp-exp-result', Settings.dialog); - $.rmAll(p); - $.add(p, a); - return a.click(); - }, - "import": function() { - return $('input[type=file]', this.parentNode).click(); - }, - onImport: function() { - var file, output, reader; - if (!(file = this.files[0])) { - return; - } - this.value = null; - 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 err; - try { - return Settings.loadSettings($.dict.json(e.target.result), function(err) { - if (err) { - return output.textContent = 'Import failed due to an error.'; - } else if (confirm('Import successful. Reload now?')) { - return window.location.reload(); - } - }); - } catch (error) { - err = error; - output.textContent = 'Import failed due to an error.'; - return c.error(err.stack); - } - }; - return reader.readAsText(file); - }, - convertFrom: { - loadletter: function(data) { - var base, boardID, convertSettings, key, ref, ref1, threadData, threadID, threads, val; - convertSettings = function(data, map) { - var newKey, prevKey; - for (prevKey in map) { - newKey = map[prevKey]; - if (newKey) { - data.Conf[newKey] = data.Conf[prevKey]; - } - delete data.Conf[prevKey]; - } - return data; - }; - data = convertSettings(data, { - 'Disable 4chan\'s extension': 'Disable Native Extension', - 'Comment Auto-Expansion': '', - 'Remove Slug': '', - 'Always HTTPS': 'Redirect to HTTPS', - 'Check for Updates': '', - 'Recursive Filtering': 'Recursive Hiding', - 'Reply Hiding': 'Reply Hiding Buttons', - 'Thread Hiding': 'Thread Hiding Buttons', - 'Show Stubs': 'Stubs', - 'Image Auto-Gif': 'Replace GIF', - 'Expand All WebM': 'Expand videos', - 'Reveal Spoilers': 'Reveal Spoiler Thumbnails', - 'Expand From Current': 'Expand from here', - 'Current Page': 'Page Count in Stats', - 'Current Page Position': '', - 'Alternative captcha': 'Use Recaptcha v1', - 'Alt index captcha': 'Use Recaptcha v1 on Index', - 'Auto Submit': 'Post on Captcha Completion', - 'Open Reply in New Tab': 'Open Post in New Tab', - 'Remember QR size': 'Remember QR Size', - 'Remember Subject': '', - 'Quote Inline': 'Quote Inlining', - 'Quote Preview': 'Quote Previewing', - 'Indicate OP quote': 'Mark OP Quotes', - 'Indicate You quote': 'Mark Quotes of You', - 'Indicate Cross-thread Quotes': 'Mark Cross-thread Quotes', - 'uniqueid': 'uniqueID', - 'mod': 'capcode', - 'email': '', - 'country': 'flag', - 'md5': 'MD5', - 'openEmptyQR': 'Open empty QR', - 'openQR': 'Open QR', - 'openOptions': 'Open settings', - 'close': 'Close', - 'spoiler': 'Spoiler tags', - 'sageru': 'Toggle sage', - 'code': 'Code tags', - 'sjis': 'SJIS tags', - 'submit': 'Submit QR', - 'watch': 'Watch', - 'update': 'Update', - 'unreadCountTo0': '', - 'expandAllImages': 'Expand images', - 'expandImage': 'Expand image', - 'zero': 'Front page', - 'nextPage': 'Next page', - 'previousPage': 'Previous page', - 'nextThread': 'Next thread', - 'previousThread': 'Previous thread', - 'expandThread': 'Expand thread', - 'openThreadTab': 'Open thread', - 'openThread': 'Open thread tab', - 'nextReply': 'Next reply', - 'previousReply': 'Previous reply', - 'hide': 'Hide', - 'Scrolling': 'Auto Scroll', - 'Verbose': '' - }); - if ('Always CDN' in data.Conf) { - data.Conf['fourchanImageHost'] = data.Conf['Always CDN'] ? 'i.4cdn.org' : ''; - delete data.Conf['Always CDN']; - } - data.Conf.sauces = data.Conf.sauces.replace(/\$\d/g, function(c) { - switch (c) { - case '$1': - return '%TURL'; - case '$2': - return '%URL'; - case '$3': - return '%MD5'; - case '$4': - return '%board'; - default: - return c; - } - }); - ref = Config.hotkeys; - for (key in ref) { - val = ref[key]; - if (key in data.Conf) { - data.Conf[key] = data.Conf[key].replace(/ctrl|alt|meta/g, function(s) { - return "" + (s[0].toUpperCase()) + s.slice(1); - }).replace(/(^|.+\+)[A-Z]$/g, function(s) { - return "Shift+" + s.slice(0, -1) + (s.slice(-1).toLowerCase()); - }); - } - } - if (data.WatchedThreads) { - data.Conf['watchedThreads'] = $.dict.clone({ - '4chan.org': { - boards: {} - } - }); - ref1 = data.WatchedThreads; - for (boardID in ref1) { - threads = ref1[boardID]; - for (threadID in threads) { - threadData = threads[threadID]; - ((base = data.Conf['watchedThreads']['4chan.org'].boards)[boardID] || (base[boardID] = $.dict()))[threadID] = { - excerpt: threadData.textContent - }; - } - } - } - return data; - } - }, - upgrade: function(data, version) { - var addCSS, addSauces, boardID, boards, changes, compareString, corrupted, db, hostname, j, k, key, l, lastChecked, len, len1, len2, len3, line, list, m, name, record, ref, ref1, ref10, ref11, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, rice, set, setD, siteProperties, software, type, uids, val, val2, value; - changes = $.dict(); - set = function(key, value) { - return data[key] = changes[key] = value; - }; - setD = function(key, value) { - if (data[key] == null) { - return set(key, value); - } - }; - addSauces = function(sauces) { - if (data['sauces'] != null) { - sauces = sauces.filter(function(s) { - return data['sauces'].indexOf(s.match(/[^#;\s]+|$/)[0]) < 0; - }); - if (sauces.length) { - return set('sauces', data['sauces'] + '\n\n' + sauces.join('\n')); - } - } - }; - addCSS = function(css) { - if (data['usercss'] == null) { - set('usercss', Config['usercss']); - } - if (data['usercss'].indexOf(css) < 0) { - return set('usercss', css + '\n\n' + data['usercss']); - } - }; - if ((corrupted = version[0] === '"')) { - try { - version = JSON.parse(version); - } catch (error) {} - } - compareString = version.replace(/\d+/g, function(x) { - return ('0000' + x).slice(-5); - }); - if (compareString < '00001.00013.00014.00008') { - for (key in data) { - val = data[key]; - if (!(typeof val === 'string' && typeof Conf[key] !== 'string' && (key !== 'Index Sort' && key !== 'Last Long Reply Thresholds 0' && key !== 'Last Long Reply Thresholds 1'))) { - continue; - } - corrupted = true; - break; - } - } - if (corrupted) { - for (key in data) { - val = data[key]; - if (typeof val === 'string') { - try { - val2 = JSON.parse(val); - set(key, val2); - } catch (error) {} - } - } - } - if (compareString < '00001.00011.00008.00000') { - if (data['Fixed Thread Watcher'] == null) { - set('Fixed Thread Watcher', (ref = data['Toggleable Thread Watcher']) != null ? ref : true); - } - if (data['Exempt Archives from Encryption'] == null) { - set('Exempt Archives from Encryption', (ref1 = data['Except Archives from Encryption']) != null ? ref1 : false); - } - } - if (compareString < '00001.00011.00010.00001') { - if (data['selectedArchives'] != null) { - uids = { - "Moe": 0, - "4plebs Archive": 3, - "Nyafuu Archive": 4, - "Love is Over": 5, - "Rebecca Black Tech": 8, - "warosu": 10, - "fgts": 15, - "not4plebs": 22, - "DesuStorage": 23, - "fireden.net": 24, - "disabled": null - }; - ref2 = data['selectedArchives']; - for (boardID in ref2) { - record = ref2[boardID]; - for (type in record) { - name = record[type]; - if ($.hasOwn(uids, name)) { - record[type] = uids[name]; - } - } - } - set('selectedArchives', data['selectedArchives']); - } - } - if (compareString < '00001.00011.00016.00000') { - if ((rice = Config['usercss'].match(/\/\* Board title rice \*\/(?:\n.+)*/)[0])) { - if ((data['usercss'] != null) && data['usercss'].indexOf(rice) < 0) { - set('usercss', rice + '\n\n' + data['usercss']); - } - } - } - if (compareString < '00001.00011.00017.00000') { - ref3 = ['Persistent QR', 'Color User IDs', 'Fappe Tyme', 'Werk Tyme', 'Highlight Posts Quoting You', 'Highlight Own Posts']; - for (j = 0, len = ref3.length; j < len; j++) { - key = ref3[j]; - if (data[key] == null) { - set(key, key === 'Persistent QR'); - } - } - } - if (compareString < '00001.00011.00017.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/iqdb\.org\//mg, '$1//iqdb.org/')); - } - } - if (compareString < '00001.00011.00019.00003' && !Settings.dialog) { - $.queueTask(function() { - return Settings.warnings.ads(function(item) { - return new Notice('warning', slice.call(item.childNodes)); - }); - }); - } - if (compareString < '00001.00011.00020.00003') { - ref4 = { - 'Inline Cross-thread Quotes Only': false, - 'Pass Link': true - }; - for (key in ref4) { - value = ref4[key]; - if (data[key] == null) { - set(key, value); - } - } - } - if (compareString < '00001.00011.00021.00003') { - if (data['Remember Your Posts'] == null) { - set('Remember Your Posts', (ref5 = data['Mark Quotes of You']) != null ? ref5 : true); - } - } - if (compareString < '00001.00011.00022.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|URL))%3Fs\.jpg/mg, '$1')); - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(?:IMG|T?URL)(?=$|;)/mg, '$&&safe=off')); - } - } - if (compareString < '00001.00011.00022.00002') { - if ((data['Use Recaptcha v1 in Reports'] == null) && data['Use Recaptcha v1'] && !data['Use Recaptcha v2 in Reports']) { - set('Use Recaptcha v1 in Reports', true); - } - } - if (compareString < '00001.00011.00024.00000') { - if ((data['JSON Navigation'] != null) && (data['JSON Index'] == null)) { - set('JSON Index', data['JSON Navigation']); - } - } - if (compareString < '00001.00011.00026.00000') { - if ((data['Oekaki Links'] != null) && (data['Edit Link'] == null)) { - set('Edit Link', data['Oekaki Links']); - } - if (data['Inline Cross-thread Quotes Only'] == null) { - set('Inline Cross-thread Quotes Only', true); - } - } - if (compareString < '00001.00011.00030.00000') { - if (data['Quote Threading'] && (data['Thread Quotes'] == null)) { - set('Thread Quotes', true); - } - } - if (compareString < '00001.00011.00032.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/3d\.iqdb\.org\//mg, '$1//3d.iqdb.org/')); - } - addSauces(['#https://desustorage.org/_/search/image/%sMD5/', '#https://boards.fireden.net/_/search/image/%sMD5/', '#https://foolz.fireden.net/_/search/image/%sMD5/', '#//www.gif-explode.com/%URL;types:gif']); - } - if (compareString < '00001.00011.00035.00000') { - addSauces(['https://whatanime.ga/?auto&url=%IMG;text:wait']); - } - if (compareString < '00001.00012.00000.00000') { - if (data['Exempt Archives from Encryption'] == null) { - set('Exempt Archives from Encryption', false); - } - if (data['Show New Thread Option in Threads'] == null) { - set('Show New Thread Option in Threads', false); - } - if (data['Show Name and Subject']) { - addCSS('#qr .persona .field {display: block !important;}'); - } - if (data['QR Shortcut'] === false) { - addCSS('#shortcut-qr {display: none;}'); - } - if (data['Bottom QR Link'] === false) { - addCSS('.qr-link-container-bottom {display: none;}'); - } - } - if (compareString < '00001.00012.00000.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)https:\/\/(?:desustorage|cuckchan)\.org\//mg, '$1https://desuarchive.org/')); - } - } - if (compareString < '00001.00012.00001.00000') { - if ((data['Persistent Thread Watcher'] == null) && (data['Toggleable Thread Watcher'] != null)) { - set('Persistent Thread Watcher', !data['Toggleable Thread Watcher']); - } - } - if (compareString < '00001.00012.00003.00000') { - ref6 = ['Image Hover in Catalog', 'Auto Watch', 'Auto Watch Reply']; - for (k = 0, len1 = ref6.length; k < len1; k++) { - key = ref6[k]; - setD(key, false); - } - } - if (compareString < '00001.00013.00001.00002') { - addSauces(['#//www.bing.com/images/search?q=imgurl:%IMG&view=detailv2&iss=sbi#enterInsights']); - } - if (compareString < '00001.00013.00005.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)http:\/\/regex\.info\/exif\.cgi/mg, '$1http://exif.regex.info/exif.cgi')); - } - addSauces(Config['sauces'].match(/# Known filename formats:(?:\n.+)*|$/)[0].split('\n')); - } - if (compareString < '00001.00013.00007.00002') { - setD('Require OP Quote Link', true); - } - if (compareString < '00001.00013.00008.00000') { - setD('Download Link', true); - } - if (compareString < '00001.00013.00009.00003') { - if (data['jsWhitelist'] != null) { - list = data['jsWhitelist'].split('\n'); - if (indexOf.call(list, 'https://cdnjs.cloudflare.com') < 0 && indexOf.call(list, 'https://cdn.mathjax.org') >= 0) { - set('jsWhitelist', data['jsWhitelist'] + '\n\nhttps://cdnjs.cloudflare.com'); - } - } - } - if (compareString < '00001.00014.00000.00006') { - if (data['siteSoftware'] != null) { - set('siteSoftware', data['siteSoftware'] + '\n4cdn.org yotsuba'); - } - } - if (compareString < '00001.00014.00003.00002') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)https:\/\/whatanime\.ga\//mg, '$1https://trace.moe/')); - } - } - if (compareString < '00001.00014.00004.00004') { - if ((data['siteSoftware'] != null) && !/^4channel\.org yotsuba$/m.test(data['siteSoftware'])) { - set('siteSoftware', data['siteSoftware'] + '\n4channel.org yotsuba'); - } - } - if (compareString < '00001.00014.00005.00000') { - ref7 = DataBoard.keys; - for (l = 0, len2 = ref7.length; l < len2; l++) { - db = ref7[l]; - if ((ref8 = data[db]) != null ? ref8.boards : void 0) { - ref9 = data[db], boards = ref9.boards, lastChecked = ref9.lastChecked; - data[db]['4chan.org'] = { - boards: boards, - lastChecked: lastChecked - }; - delete data[db].boards; - delete data[db].lastChecked; - set(db, data[db]); - } - } - if ((data['siteSoftware'] != null) && (data['siteProperties'] == null)) { - siteProperties = $.dict(); - ref10 = data['siteSoftware'].split('\n'); - for (m = 0, len3 = ref10.length; m < len3; m++) { - line = ref10[m]; - ref11 = line.split(' '), hostname = ref11[0], software = ref11[1]; - siteProperties[hostname] = { - software: software - }; - } - set('siteProperties', siteProperties); - } - } - if (compareString < '00001.00014.00006.00006') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/\/\/%\$1\.deviantart\.com\/gallery\/#\/d%\$2;regexp:\/\^\\w\+_by_\(\\w\+\)-d\(\[\\da-z\]\+\)\//g, '//www.deviantart.com/gallery/#/d%$1%$2;regexp:/^\\w+_by_\\w+[_-]d([\\da-z]{6})\\b|^d([\\da-z]{6})-[\\da-z]{8}-/')); - } - } - if (compareString < '00001.00014.00008.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/https:\/\/www\.yandex\.com\/images\/search/g, 'https://yandex.com/images/search')); - } - } - if (compareString < '00001.00014.00009.00000') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^(#?\s*)(?:http:)?\/\/(www\.pixiv\.net|www\.deviantart\.com|imgur\.com|flickr\.com)\//mg, '$1https://$2/')); - set('sauces', data['sauces'].replace(/https:\/\/yandex\.com\/images\/search\?rpt=imageview&img_url=%IMG/g, 'https://yandex.com/images/search?rpt=imageview&url=%IMG')); - } - } - if (compareString < '00001.00014.00009.00001') { - if ((data['Use Faster Image Host'] != null) && (data['fourchanImageHost'] == null)) { - set('fourchanImageHost', (data['Use Faster Image Host'] ? 'i.4cdn.org' : '')); - } - } - if (compareString < '00001.00014.00010.00001') { - if (data['Filter in Native Catalog'] == null) { - set('Filter in Native Catalog', false); - } - } - if (compareString < '00001.00014.00012.00008') { - if (data['boardnav'] == null) { - set('boardnav', "[ toggle-all ]\na-replace\nc-replace\ng-replace\nk-replace\nv-replace\nvg-replace\nvr-replace\nck-replace\nco-replace\nfit-replace\njp-replace\nmu-replace\nsp-replace\ntv-replace\nvp-replace\n[external-text:\"FAQ\",\"https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions\"]"); - } - } - if (compareString < '00001.00014.00016.00001') { - if (data['archiveLists'] != null) { - set('archiveLists', data['archiveLists'].replace('https://mayhemydg.github.io/archives.json/archives.json', 'https://nstepien.github.io/archives.json/archives.json')); - } - } - if (compareString < '00001.00014.00016.00007') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/https:\/\/www\.deviantart\.com\/gallery\/#\/d%\$1%\$2;regexp:\/\^\\w\+_by_\\w\+\[_-\]d\(\[\\da-z\]\{6\}\)\\b\|\^d\(\[\\da-z\]\{6\}\)-\[\\da-z\]\{8\}-\//g, 'javascript:void(open("https://www.deviantart.com/"+%$1.replace(/_/g,"-")+"/art/"+parseInt(%$2,36)));regexp:/^\\w+_by_(\\w+)[_-]d([\\da-z]{6})\\b/').replace(/\/\/imgops\.com\/%URL/g, '//imgops.com/start?url=%URL')); - } - } - if (compareString < '00001.00014.00017.00002') { - if (data['jsWhitelist'] != null) { - set('jsWhitelist', data['jsWhitelist'] + '\n\nhttps://hcaptcha.com\nhttps://*.hcaptcha.com'); - } - } - if (compareString < '00001.00014.00020.00004') { - if (data['archiveLists'] != null) { - set('archiveLists', data['archiveLists'].replace('https://nstepien.github.io/archives.json/archives.json', 'https://4chenz.github.io/archives.json/archives.json')); - } - } - if (compareString < '00001.00014.00022.00003') { - if (data['sauces'] != null) { - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/www\.google\.com\/searchbyimage\?image_url=%(IMG|T?URL)&safe=off(?=$|;)/mg, 'https://www.google.com/searchbyimage?sbisrc=4chanx&image_url=%$1&safe=off')); - if (compareString === '00001.00014.00022.00002' && !/\bsbisrc=/.test(data['sauces'])) { - set('sauces', data['sauces'].replace(/^#?\s*https:\/\/lens\.google\.com\/uploadbyurl\?url=%(IMG|T?URL)(?=$|;)/m, 'https://www.google.com/searchbyimage?sbisrc=4chanx&image_url=%$1&safe=off')); - } - } - addSauces(['#https://lens.google.com/uploadbyurl?url=%IMG;text:lens']); - } - return changes; - }, - loadSettings: function(data, cb) { - if (data.version.split('.')[0] === '2') { - data = Settings.convertFrom.loadletter(data); - } else if (data.version !== g.VERSION) { - Settings.upgrade(data.Conf, data.version); - } - return $.clear(function(err) { - if (err) { - return cb(err); - } - return $.set(data.Conf, cb); - }); - }, - reset: function() { - if (confirm('Your current settings will be entirely wiped, are you sure?')) { - return $.clear(function(err) { - if (err) { - return $('.imp-exp-result').textContent = 'Import failed due to an error.'; - } else if (confirm('Reset successful. Reload now?')) { - return window.location.reload(); - } - }); - } - }, - filter: function(section) { - var select; - $.extend(section, {innerHTML: "
      "}); - select = $('select', section); - $.on(select, 'change', Settings.selectFilter); - return Settings.selectFilter.call(select); - }, - selectFilter: function() { - var div, filterTypes, name, ta; - div = this.nextElementSibling; - if ((name = this.value) !== 'guide') { - if (!$.hasOwn(Config.filter, name)) { - return; - } - $.rmAll(div); - ta = $.el('textarea', { - name: name, - className: 'field', - spellcheck: false - }); - $.on(ta, 'change', $.cb.value); - $.get(name, Conf[name], function(item) { - ta.value = item[name]; - return $.add(div, ta); - }); - return; - } - filterTypes = Object.keys(Config.filter).filter(function(x) { - return x !== 'general'; - }).map(function(x, i) { - return {innerHTML: ((i) ? "," : "") + "" + E(x)}; - }); - $.extend(div, {innerHTML: "
      Filter is disabled.

      Use regular expressions, one per line.
      Lines starting with a # will be ignored.
      For example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
      MD5 and Unique ID filtering use exact string matching, not regular expressions.

        You can use these settings with each regular expression, separate them with semicolons:
      • Per boards, separate them with commas. It is global if not specified. Use sfw and nsfw to reference all worksafe or not-worksafe boards.
        For example: boards:a,jp;.
        To specify boards on a particular site, put the beginning of the domain and a slash character before the list.
        Any initial www. should not be included, and all 4chan domains are considered 4chan.org.
        For example: boards:4:a,jp,sama:a,z;.
        An asterisk can be used to specify all boards on a site.
        For example: boards:4:*;.
      • Select boards to be excluded from the filter. The syntax is the same as for the boards: option above.
        For example: exclude:vg,v;.
      • Filter OPs only along with their threads (`only`) or replies only (`no`).
        For example: op:only; or op:no;.
      • Filter only posts with files (`only`) or only posts without files (`no`).
        For example: file:only; or file:no;.
      • Overrule the `Show Stubs` setting if specified: create a stub (`yes`) or not (`no`).
        For example: stub:yes; or stub:no;.
      • Highlight instead of hiding. You can specify a class name to use with a userstyle.
        For example: highlight; or highlight:wallpaper;.
      • Highlighted OPs will have their threads put on top of the board index by default.
        For example: top:yes; or top:no;.
      • Show a desktop notification instead of hiding.
        For example: notify;.
      • Filters in the \"General\" section apply to multiple fields, by default subject,name,filename,comment.
        The fields can be specified with the type option, separated by commas.
        For example: type:" + E.cat(filterTypes) + ";.
        Types can also be combined with a + sign; this indicates the filter applies to the given fields joined by newlines.
        For example: type:filename+filesize+dimensions;.
      "}); - return $('.warning', div).hidden = Conf['Filter']; - }, - sauce: function(section) { - var ta; - $.extend(section, {innerHTML: "
      Sauce is disabled.
      These parameters will be replaced by their corresponding values in the URL and displayed text:
      • %IMG: Full image URL for GIF, JPG, and PNG; thumbnail URL for other types.
      • %URL: Full image URL.
      • %TURL: Thumbnail URL.
      • %name: Original file name.
      • %board: Current board.
      • %MD5: MD5 hash in base64.
      • %sMD5: MD5 hash in base64 using - and _.
      • %hMD5: MD5 hash in hexadecimal.
      • %$0: Matched regular expression within the filename.
      • %$1, %$2, %$3, ... : Subexpressions within the matched regular expression.
      • %%, %semi: Literal % and ;.
      Lines starting with a # will be ignored.
      You can specify a display text by appending ;text:[text] to the URL.
      You can specify the applicable boards/sites by appending ;boards:[board1],[board2]. See the Filter guide for details.
      You can specify the applicable file types by appending ;types:[extension1],[extension2].
      You can specify a regular expression the filename must match by appending ;regexp:[regular expression].
      "}); - $('.warning', section).hidden = Conf['Sauce']; - ta = $('textarea', section); - $.get('sauces', Conf['sauces'], function(item) { - ta.value = item['sauces']; - return ta.hidden = false; - }); - return $.on(ta, 'change', $.cb.value); - }, - advanced: function(section) { - var applyCSS, boardSelect, customCSS, event, input, inputs, interval, items, itemsArchive, j, k, l, len, len1, len2, len3, listImageHost, m, name, ref, ref1, ref2, ref3, ref4, table, textContent, updateArchives, warning; - $.extend(section, {innerHTML: "
      Archives
      404 Redirect is disabled.
      Thread redirectionPost fetchingFile redirection

      Archive Lists: Each line below should be an archive list in this format or a URL to load an archive list from.
      Archive properties can be overriden by another item with the same uid (or if absent, its name).
      Last updated:
      External Catalog
      External Catalog is disabled. This will be used only as a fallback.
      URLs of external catalog sites, where %board is to be replaced by the board name.
      Each URL should be followed by ;boards: and optionally ;exclude: and a list of supported/excluded boards in the format explained in the Filter guide.
      Override 4chan Image Host
      Change 4chan image links to this domain. Leave blank for no change.
      Captcha Language
      Choose from list of language codes. Leave blank to autoselect.
      Custom Board Navigation
      New lines will be converted into spaces.

      In the following examples for /g/, g can be changed to a different board ID (a, b, etc...), the current board (current), or the Twitter link (@).
      Board link: g
      Archive link: g-archive
      Internal archive link: g-expired
      Title link: g-title
      Board link (Replace with title when on that board): g-replace
      Full text link: g-full
      Custom text link: g-text:"Install Gentoo"
      Index-only link: g-index
      Catalog-only link: g-catalog
      Index mode: g-mode:"infinite scrolling"
      Index sort: g-sort:"creation date rev"
      External link: external-text:"Google","http://www.google.com"
      Open in new tab: g-nt
      Combinations are possible: g-index-text:"Technology Index"
      Full board list toggle: toggle-all

      [ toggle-all ] [current-title] [g-title / a-title / jp-title] [x / wsg / h] [t-text:"Piracy"]
      will give you
      [ + ] [Technology] [Technology / Anime & Manga / Otaku Culture] [x / wsg / h] [Piracy]
      if you are on /g/.
      Time Formatting is disabled.
      :
      Day: %a, %A, %d, %e
      Month: %m, %b, %B
      Year: %y, %Y
      Hour: %k, %H, %l, %I, %p, %P
      Minute: %M
      Second: %S
      Literal %: %%
      Quote Backlinks formatting is disabled.
      :
      Default pasted content filename
      .png
      File Info Formatting is disabled.
      :
      Link: %l (truncated), %L (untruncated), %T (4chan filename)
      Filename: %n (truncated), %N (untruncated), %t (4chan filename)
      Download button: %d
      Quick filter MD5: %f
      Spoiler indicator: %p
      Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default)
      Resolution: %r (Displays 'PDF' for PDF files)
      Tag: %g
      Literal %: %%
      Quick Reply Personas

      One item per line.
      Items will be added in the relevant input's auto-completion list.
      Password items will always be used, since there is no password input.
      Lines starting with a # will be ignored.

        You can use these settings with each item, separate them with semicolons:
      • Possible items are: name, options (or equivalently email), subject and password.
      • Wrap values of items with quotes, like this: options:"sage".
      • Force values as defaults with the always keyword, for example: options:"sage";always.
      • Select specific boards for an item, separated with commas, for example: options:"sage";boards:jp;always.
      Unread Favicon is disabled.
      Thread Updater is disabled.
      Interval: seconds
      Custom Cooldown Time
      Seconds:
      For more information about customizing 4chan X's CSS, see the styling guide.
      Javascript Whitelist
      Sources from which Javascript is allowed to be loaded by Content Security Policy.
      Lines starting with a # will be ignored.
      Known Banners
      List of known banners, used for click-to-change feature.
      "}); - ref = $$('.warning', section); - for (j = 0, len = ref.length; j < len; j++) { - warning = ref[j]; - warning.hidden = Conf[warning.dataset.feature]; - } - inputs = $.dict(); - ref1 = $$('[name]', section); - for (k = 0, len1 = ref1.length; k < len1; k++) { - input = ref1[k]; - inputs[input.name] = input; - } - $.on(inputs['archiveLists'], 'change', function() { - $.set('lastarchivecheck', 0); - Conf['lastarchivecheck'] = 0; - return $.id('lastarchivecheck').textContent = 'never'; - }); - items = $.dict(); - for (name in inputs) { - input = inputs[name]; - if (!(name !== 'Interval' && name !== 'Custom CSS')) { - continue; - } - items[name] = Conf[name]; - event = (input.nodeName === 'SELECT' || ((ref2 = input.type) === 'checkbox' || ref2 === 'radio') || (input.nodeName === 'TEXTAREA' && !(name in Settings))) ? 'change' : 'input'; - $.on(input, event, $.cb[input.type === 'checkbox' ? 'checked' : 'value']); - if (name in Settings) { - $.on(input, event, Settings[name]); - } - } - $.get(items, function(items) { - var key, val; - for (key in items) { - val = items[key]; - input = inputs[key]; - input[input.type === 'checkbox' ? 'checked' : 'value'] = val; - input.hidden = false; - if (key in Settings) { - Settings[key].call(input); - } - } - }); - listImageHost = $.id('list-fourchanImageHost'); - ref3 = ImageHost.suggestions; - for (l = 0, len2 = ref3.length; l < len2; l++) { - textContent = ref3[l]; - $.add(listImageHost, $.el('option', { - textContent: textContent - })); - } - interval = inputs['Interval']; - customCSS = inputs['Custom CSS']; - applyCSS = $('#apply-css', section); - interval.value = Conf['Interval']; - customCSS.checked = Conf['Custom CSS']; - inputs['usercss'].disabled = !Conf['Custom CSS']; - applyCSS.disabled = !Conf['Custom CSS']; - $.on(interval, 'change', ThreadUpdater.cb.interval); - $.on(customCSS, 'change', Settings.togglecss); - $.on(applyCSS, 'click', function() { - return CustomCSS.update(); - }); - itemsArchive = $.dict(); - ref4 = ['archives', 'selectedArchives', 'lastarchivecheck']; - for (m = 0, len3 = ref4.length; m < len3; m++) { - name = ref4[m]; - itemsArchive[name] = Conf[name]; - } - $.get(itemsArchive, function(itemsArchive) { - $.extend(Conf, itemsArchive); - Redirect.selectArchives(); - return Settings.addArchiveTable(section); - }); - boardSelect = $('#archive-board-select', section); - table = $('#archive-table', section); - updateArchives = $('#update-archives', section); - $.on(boardSelect, 'change', function() { - $('tbody > :not([hidden])', table).hidden = true; - return $("tbody > ." + this.value, table).hidden = false; - }); - return $.on(updateArchives, 'click', function() { - return Redirect.update(function() { - return Settings.addArchiveTable(section); - }); - }); - }, - addArchiveTable: function(section) { - var archBoards, archive, boardID, boardOptions, boardSelect, boards, data, files, id, item, j, k, l, len, len1, len2, len3, m, name, o, ref, ref1, ref2, ref3, ref4, row, rows, select, software, table, tbody, type, uid; - $('#lastarchivecheck', section).textContent = Conf['lastarchivecheck'] === 0 ? 'never' : new Date(Conf['lastarchivecheck']).toLocaleString(); - boardSelect = $('#archive-board-select', section); - table = $('#archive-table', section); - tbody = $('tbody', section); - $.rmAll(boardSelect); - $.rmAll(tbody); - archBoards = $.dict(); - ref = Conf['archives']; - for (j = 0, len = ref.length; j < len; j++) { - ref1 = ref[j], uid = ref1.uid, name = ref1.name, boards = ref1.boards, files = ref1.files, software = ref1.software; - if (software !== 'fuuka' && software !== 'foolfuuka') { - continue; - } - for (k = 0, len1 = boards.length; k < len1; k++) { - boardID = boards[k]; - o = archBoards[boardID] || (archBoards[boardID] = { - thread: [], - post: [], - file: [] - }); - archive = [uid != null ? uid : name, name]; - o.thread.push(archive); - if (software === 'foolfuuka') { - o.post.push(archive); - } - if (indexOf.call(files, boardID) >= 0) { - o.file.push(archive); - } - } - } - rows = []; - boardOptions = []; - ref2 = Object.keys(archBoards).sort(); - for (l = 0, len2 = ref2.length; l < len2; l++) { - boardID = ref2[l]; - row = $.el('tr', { - className: "board-" + boardID - }); - row.hidden = boardID !== g.BOARD.ID; - boardOptions.push($.el('option', { - textContent: "/" + boardID + "/", - value: "board-" + boardID, - selected: boardID === g.BOARD.ID - })); - o = archBoards[boardID]; - ref3 = ['thread', 'post', 'file']; - for (m = 0, len3 = ref3.length; m < len3; m++) { - item = ref3[m]; - $.add(row, Settings.addArchiveCell(boardID, o, item)); - } - rows.push(row); - } - if (rows.length === 0) { - boardSelect.hidden = table.hidden = true; - return; - } - boardSelect.hidden = table.hidden = false; - if (!(g.BOARD.ID in archBoards)) { - rows[0].hidden = false; - } - $.add(boardSelect, boardOptions); - $.add(tbody, rows); - ref4 = Conf['selectedArchives']; - for (boardID in ref4) { - data = ref4[boardID]; - for (type in data) { - id = data[type]; - if ((select = $("select[data-boardid='" + boardID + "'][data-type='" + type + "']", tbody))) { - select.value = JSON.stringify(id); - if (!select.value) { - select.value = select.firstChild.value; - } - } - } - } - }, - addArchiveCell: function(boardID, data, type) { - var archive, i, length, options, select, td; - length = data[type].length; - td = $.el('td', { - className: 'archive-cell' - }); - if (!length) { - td.textContent = '--'; - return td; - } - options = []; - i = 0; - while (i < length) { - archive = data[type][i++]; - options.push($.el('option', { - value: JSON.stringify(archive[0]), - textContent: archive[1] - })); - } - $.extend(td, {innerHTML: ""}); - select = td.firstElementChild; - if (!(select.disabled = length === 1)) { - select.setAttribute('data-boardid', boardID); - select.setAttribute('data-type', type); - $.on(select, 'change', Settings.saveSelectedArchive); - } - $.add(select, options); - return td; - }, - saveSelectedArchive: function() { - return $.get('selectedArchives', Conf['selectedArchives'], (function(_this) { - return function(arg) { - var name1, selectedArchives; - selectedArchives = arg.selectedArchives; - (selectedArchives[name1 = _this.dataset.boardid] || (selectedArchives[name1] = $.dict()))[_this.dataset.type] = JSON.parse(_this.value); - $.set('selectedArchives', selectedArchives); - Conf['selectedArchives'] = selectedArchives; - return Redirect.selectArchives(); - }; - })(this)); - }, - boardnav: function() { - return Header.generateBoardList(this.value); - }, - time: function() { - return this.nextElementSibling.textContent = Time.format(this.value, new Date()); - }, - timeLocale: function() { - return Settings.time.call($('[name=time]', Settings.dialog)); - }, - backlink: function() { - return this.nextElementSibling.textContent = this.value.replace(/%(?:id|%)/g, function(x) { - return { - '%id': '123456789', - '%%': '%' - }[x]; - }); - }, - fileInfo: function() { - var data; - data = { - isReply: true, - file: { - url: "//" + (ImageHost.host()) + "/g/1334437723720.jpg", - name: 'd9bb2efc98dd0df141a94399ff5880b7.jpg', - size: '276 KB', - sizeInBytes: 276 * 1024, - dimensions: '1280x720', - isImage: true, - isVideo: false, - isSpoiler: true, - tag: 'Loop' - } - }; - return FileInfo.format(this.value, data, this.nextElementSibling); - }, - favicon: function() { - var f, i, icon, img, j, len, ref; - Favicon["switch"](); - if (g.VIEW === 'thread' && Conf['Unread Favicon']) { - Unread.update(); - } - img = this.nextElementSibling.children; - f = Favicon; - ref = [f.SFW, f.unreadSFW, f.unreadSFWY, f.NSFW, f.unreadNSFW, f.unreadNSFWY, f.dead, f.unreadDead, f.unreadDeadY]; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - icon = ref[i]; - if (!img[i]) { - $.add(this.nextElementSibling, $.el('img')); - } - img[i].src = icon; - } - }, - togglecss: function() { - if ($('textarea[name=usercss]', $.x('ancestor::fieldset[1]', this)).disabled = $.id('apply-css').disabled = !this.checked) { - CustomCSS.rmStyle(); - } else { - CustomCSS.addStyle(); - } - return $.cb.checked.call(this); - }, - keybinds: function(section) { - var arr, input, inputs, items, key, ref, tbody, tr; - $.extend(section, {innerHTML: "
      Keybinds are disabled.
      Allowed keys: a-z, 0-9, Ctrl, Shift, Alt, Meta, Enter, Esc, Up, Down, Right, Left.
      Press Backspace to disable a keybind.
      ActionsKeybinds
      "}); - $('.warning', section).hidden = Conf['Keybinds']; - tbody = $('tbody', section); - items = $.dict(); - inputs = $.dict(); - ref = Config.hotkeys; - for (key in ref) { - arr = ref[key]; - tr = $.el('tr', {innerHTML: "" + E(arr[1]) + ""}); - input = $('input', tr); - input.name = key; - input.spellcheck = false; - items[key] = Conf[key]; - inputs[key] = input; - $.on(input, 'keydown', Settings.keybind); - $.add(tbody, tr); - } - return $.get(items, function(items) { - var val; - for (key in items) { - val = items[key]; - inputs[key].value = val; - } - }); - }, - 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); - } - }; - - return Settings; - -}).call(this); - -Test = (function() { - return Test; - -}).call(this); - -UI = (function() { - var Menu, UI, checkbox, dialog, drag, dragend, dragstart, hover, hoverend, hoverstart, touchend, touchmove, - bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, - slice = [].slice; - - dialog = function(id, properties) { - var child, el, i, len, move, ref; - el = $.el('div', { - className: 'dialog', - id: id - }); - $.extend(el, properties); - el.style.cssText = Conf[id + ".position"]; - move = $('.move', el); - $.on(move, 'touchstart mousedown', dragstart); - ref = move.children; - for (i = 0, len = ref.length; i < len; i++) { - child = ref[i]; - if (!child.tagName) { - continue; - } - $.on(child, 'touchstart mousedown', function(e) { - return e.stopPropagation(); - }); - } - return el; - }; - - Menu = (function() { - var currentMenu, lastToggledButton; - - currentMenu = null; - - lastToggledButton = null; - - function Menu(type) { - this.type = type; - this.addEntry = bind(this.addEntry, this); - this.onFocus = bind(this.onFocus, this); - this.keybinds = bind(this.keybinds, this); - this.close = bind(this.close, this); - this.setPosition = bind(this.setPosition, this); - $.on(d, 'AddMenuEntry', (function(_this) { - return function(arg) { - var detail; - detail = arg.detail; - if (detail.type !== _this.type) { - return; - } - delete detail.open; - return _this.addEntry(detail); - }; - })(this)); - this.entries = []; - } - - Menu.prototype.makeMenu = function() { - var menu; - menu = $.el('div', { - className: 'dialog', - id: 'menu', - tabIndex: 0 - }); - menu.dataset.type = this.type; - $.on(menu, 'click', function(e) { - return e.stopPropagation(); - }); - $.on(menu, 'keydown', this.keybinds); - return menu; - }; - - Menu.prototype.toggle = function(e, button, data) { - var previousButton; - e.preventDefault(); - e.stopPropagation(); - if (currentMenu) { - previousButton = lastToggledButton; - currentMenu.close(); - if (previousButton === button) { - return; - } - } - if (!this.entries.length) { - return; - } - return this.open(button, data); - }; - - Menu.prototype.open = function(button, data) { - var entry, i, len, menu, ref; - menu = this.menu = this.makeMenu(); - currentMenu = this; - lastToggledButton = button; - this.entries.sort(function(first, second) { - return first.order - second.order; - }); - ref = this.entries; - for (i = 0, len = ref.length; i < len; i++) { - entry = ref[i]; - this.insertEntry(entry, menu, data); - } - $.addClass(lastToggledButton, 'active'); - $.on(d, 'click CloseMenu', this.close); - $.on(d, 'scroll', this.setPosition); - $.on(window, 'resize', this.setPosition); - $.after(button, menu); - this.setPosition(); - entry = $('.entry', menu); - this.focus(entry); - return menu.focus(); - }; - - Menu.prototype.setPosition = function() { - var bLeft, bRect, bTop, bottom, cHeight, cWidth, left, mRect, ref, ref1, right, top; - mRect = this.menu.getBoundingClientRect(); - bRect = lastToggledButton.getBoundingClientRect(); - bTop = window.scrollY + bRect.top; - bLeft = window.scrollX + bRect.left; - cHeight = doc.clientHeight; - cWidth = doc.clientWidth; - ref = bRect.top + bRect.height + mRect.height < cHeight ? [bRect.bottom + "px", ''] : ['', (cHeight - bRect.top) + "px"], top = ref[0], bottom = ref[1]; - ref1 = bRect.left + mRect.width < cWidth ? [bRect.left + "px", ''] : ['', (cWidth - bRect.right) + "px"], left = ref1[0], right = ref1[1]; - $.extend(this.menu.style, { - top: top, - right: right, - bottom: bottom, - left: left - }); - return this.menu.classList.toggle('left', right); - }; - - Menu.prototype.insertEntry = function(entry, parent, data) { - var err, i, len, ref, subEntry, submenu; - if (typeof entry.open === 'function') { - try { - if (!entry.open(data)) { - return; - } - } catch (error) { - err = error; - Main.handleErrors({ - message: "Error in building the " + this.type + " menu.", - error: err - }); - return; - } - } - $.add(parent, entry.el); - if (!entry.subEntries) { - return; - } - if (submenu = $('.submenu', entry.el)) { - $.rm(submenu); - } - submenu = $.el('div', { - className: 'dialog submenu' - }); - ref = entry.subEntries; - for (i = 0, len = ref.length; i < len; i++) { - subEntry = ref[i]; - this.insertEntry(subEntry, submenu, data); - } - $.add(entry.el, submenu); - }; - - Menu.prototype.close = function() { - $.rm(this.menu); - delete this.menu; - $.rmClass(lastToggledButton, 'active'); - currentMenu = null; - lastToggledButton = null; - $.off(d, 'click scroll CloseMenu', this.close); - $.off(d, 'scroll', this.setPosition); - return $.off(window, 'resize', this.setPosition); - }; - - Menu.prototype.findNextEntry = function(entry, direction) { - var entries; - entries = slice.call(entry.parentNode.children); - entries.sort(function(first, second) { - return first.style.order - second.style.order; - }); - return entries[entries.indexOf(entry) + direction]; - }; - - Menu.prototype.keybinds = function(e) { - var entry, next, nextPrev, subEntry, submenu; - entry = $('.focused', this.menu); - while (subEntry = $('.focused', entry)) { - entry = subEntry; - } - switch (e.keyCode) { - case 27: - lastToggledButton.focus(); - this.close(); - break; - case 13: - case 32: - entry.click(); - break; - case 38: - if (next = this.findNextEntry(entry, -1)) { - this.focus(next); - } - break; - case 40: - if (next = this.findNextEntry(entry, +1)) { - this.focus(next); - } - break; - case 39: - if ((submenu = $('.submenu', entry)) && (next = submenu.firstElementChild)) { - while (nextPrev = this.findNextEntry(next, -1)) { - next = nextPrev; - } - this.focus(next); - } - break; - case 37: - if (next = $.x('parent::*[contains(@class,"submenu")]/parent::*', entry)) { - this.focus(next); - } - break; - default: - return; - } - e.preventDefault(); - return e.stopPropagation(); - }; - - Menu.prototype.onFocus = function(e) { - e.stopPropagation(); - return this.focus(e.target); - }; - - Menu.prototype.focus = function(entry) { - var bottom, cHeight, cWidth, eRect, focused, i, left, len, ref, ref1, ref2, right, sRect, style, submenu, top; - while (focused = $.x('parent::*/child::*[contains(@class,"focused")]', entry)) { - $.rmClass(focused, 'focused'); - } - ref = $$('.focused', entry); - for (i = 0, len = ref.length; i < len; i++) { - focused = ref[i]; - $.rmClass(focused, 'focused'); - } - $.addClass(entry, 'focused'); - if (!(submenu = $('.submenu', entry))) { - return; - } - sRect = submenu.getBoundingClientRect(); - eRect = entry.getBoundingClientRect(); - cHeight = doc.clientHeight; - cWidth = doc.clientWidth; - ref1 = eRect.top + sRect.height < cHeight ? ['0px', 'auto'] : ['auto', '0px'], top = ref1[0], bottom = ref1[1]; - ref2 = eRect.right + sRect.width < cWidth - 150 ? ['100%', 'auto'] : ['auto', '100%'], left = ref2[0], right = ref2[1]; - style = submenu.style; - style.top = top; - style.bottom = bottom; - style.left = left; - return style.right = right; - }; - - Menu.prototype.addEntry = function(entry) { - this.parseEntry(entry); - return this.entries.push(entry); - }; - - Menu.prototype.parseEntry = function(entry) { - var el, i, len, subEntries, subEntry; - el = entry.el, subEntries = entry.subEntries; - $.addClass(el, 'entry'); - $.on(el, 'focus mouseover', this.onFocus); - el.style.order = entry.order || 100; - if (!subEntries) { - return; - } - $.addClass(el, 'has-submenu'); - for (i = 0, len = subEntries.length; i < len; i++) { - subEntry = subEntries[i]; - this.parseEntry(subEntry); - } - }; - - return Menu; - - })(); - - dragstart = function(e) { - var el, isTouching, o, rect, ref, screenHeight, screenWidth; - if (e.type === 'mousedown' && e.button !== 0) { - return; - } - e.preventDefault(); - if (isTouching = e.type === 'touchstart') { - e = e.changedTouches[e.changedTouches.length - 1]; - } - el = $.x('ancestor::div[contains(@class,"dialog")][1]', this); - rect = el.getBoundingClientRect(); - screenHeight = doc.clientHeight; - screenWidth = doc.clientWidth; - o = { - id: el.id, - style: el.style, - dx: e.clientX - rect.left, - dy: e.clientY - rect.top, - height: screenHeight - rect.height, - width: screenWidth - rect.width, - screenHeight: screenHeight, - screenWidth: screenWidth, - isTouching: isTouching - }; - ref = Conf['Header auto-hide'] || !Conf['Fixed Header'] ? [0, 0] : Conf['Bottom Header'] ? [0, Header.bar.getBoundingClientRect().height] : [Header.bar.getBoundingClientRect().height, 0], o.topBorder = ref[0], o.bottomBorder = ref[1]; - if (isTouching) { - o.identifier = e.identifier; - o.move = touchmove.bind(o); - o.up = touchend.bind(o); - $.on(d, 'touchmove', o.move); - return $.on(d, 'touchend touchcancel', o.up); - } else { - o.move = drag.bind(o); - o.up = dragend.bind(o); - $.on(d, 'mousemove', o.move); - return $.on(d, 'mouseup', o.up); - } - }; - - touchmove = function(e) { - var i, len, ref, touch; - ref = e.changedTouches; - for (i = 0, len = ref.length; i < len; i++) { - touch = ref[i]; - if (touch.identifier === this.identifier) { - drag.call(this, touch); - return; - } - } - }; - - drag = function(e) { - var bottom, clientX, clientY, left, right, style, top; - clientX = e.clientX, clientY = e.clientY; - left = clientX - this.dx; - left = left < 10 ? 0 : this.width - left < 10 ? '' : left / this.screenWidth * 100 + '%'; - top = clientY - this.dy; - top = top < (10 + this.topBorder) ? this.topBorder + 'px' : this.height - top < (10 + this.bottomBorder) ? '' : top / this.screenHeight * 100 + '%'; - right = left === '' ? 0 : ''; - bottom = top === '' ? this.bottomBorder + 'px' : ''; - style = this.style; - style.left = left; - style.right = right; - style.top = top; - return style.bottom = bottom; - }; - - touchend = function(e) { - var i, len, ref, touch; - ref = e.changedTouches; - for (i = 0, len = ref.length; i < len; i++) { - touch = ref[i]; - if (touch.identifier === this.identifier) { - dragend.call(this); - return; - } - } - }; - - dragend = function() { - if (this.isTouching) { - $.off(d, 'touchmove', this.move); - $.off(d, 'touchend touchcancel', this.up); - } else { - $.off(d, 'mousemove', this.move); - $.off(d, 'mouseup', this.up); - } - return $.set(this.id + ".position", this.style.cssText); - }; - - hoverstart = function(arg) { - var cb, el, endEvents, height, latestEvent, noRemove, o, rect, ref, root, width; - root = arg.root, el = arg.el, latestEvent = arg.latestEvent, endEvents = arg.endEvents, height = arg.height, width = arg.width, cb = arg.cb, noRemove = arg.noRemove; - rect = root.getBoundingClientRect(); - o = { - root: root, - el: el, - style: el.style, - isImage: (ref = el.nodeName) === 'IMG' || ref === 'VIDEO', - cb: cb, - endEvents: endEvents, - latestEvent: latestEvent, - clientHeight: doc.clientHeight, - clientWidth: doc.clientWidth, - height: height, - width: width, - noRemove: noRemove, - clientX: (rect.left + rect.right) / 2, - clientY: (rect.top + rect.bottom) / 2 - }; - o.hover = hover.bind(o); - o.hoverend = hoverend.bind(o); - o.hover(o.latestEvent); - new MutationObserver(function() { - if (el.parentNode) { - return o.hover(o.latestEvent); - } - }).observe(el, { - childList: true - }); - $.on(root, endEvents, o.hoverend); - if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) { - $.on(d, 'keydown', o.hoverend); - } - $.on(root, 'mousemove', o.hover); - o.workaround = function(e) { - if (!root.contains(e.target)) { - return o.hoverend(e); - } - }; - return $.on(doc, 'mousemove', o.workaround); - }; - - hoverstart.padding = 25; - - hover = function(e) { - var clientX, clientY, height, left, marginX, ref, ref1, right, style, threshold, top, width; - this.latestEvent = e; - height = (this.height || this.el.offsetHeight) + hoverstart.padding; - width = this.width || this.el.offsetWidth; - ref = Conf['Follow Cursor'] ? e : this, clientX = ref.clientX, clientY = ref.clientY; - top = this.isImage ? Math.max(0, clientY * (this.clientHeight - height) / this.clientHeight) : Math.max(0, Math.min(this.clientHeight - height, clientY - 120)); - threshold = this.clientWidth / 2; - if (!this.isImage) { - threshold = Math.max(threshold, this.clientWidth - 400); - } - marginX = (clientX <= threshold ? clientX : this.clientWidth - clientX) + 45; - if (this.isImage) { - marginX = Math.min(marginX, this.clientWidth - width); - } - marginX += 'px'; - ref1 = clientX <= threshold ? [marginX, ''] : ['', marginX], left = ref1[0], right = ref1[1]; - style = this.style; - style.top = top + 'px'; - style.left = left; - return style.right = right; - }; - - hoverend = function(e) { - if (e.type === 'keydown' && e.keyCode !== 13 || e.target.nodeName === "TEXTAREA") { - return; - } - if (!this.noRemove) { - $.rm(this.el); - } - $.off(this.root, this.endEvents, this.hoverend); - $.off(d, 'keydown', this.hoverend); - $.off(this.root, 'mousemove', this.hover); - $.off(doc, 'mousemove', this.workaround); - if (this.cb) { - return this.cb.call(this); - } - }; - - checkbox = function(name, text, checked) { - var input, label; - if (checked == null) { - checked = Conf[name]; - } - label = $.el('label'); - input = $.el('input', { - type: 'checkbox', - name: name, - checked: checked - }); - $.add(label, [input, $.tn(" " + text)]); - return label; - }; - - UI = { - dialog: dialog, - Menu: Menu, - hover: hoverstart, - checkbox: checkbox - }; - - return UI; - -}).call(this); - -FappeTyme = (function() { - var FappeTyme; - - FappeTyme = { - init: function() { - var el, i, indicator, lc, len, ref, ref1, type; - if (!((Conf['Fappe Tyme'] || Conf['Werk Tyme']) && ((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive'))) { - return; - } - this.nodes = {}; - this.enabled = { - fappe: false, - werk: Conf['werk'] - }; - ref1 = ["Fappe", "Werk"]; - for (i = 0, len = ref1.length; i < len; i++) { - type = ref1[i]; - if (!Conf[type + " Tyme"]) { - continue; - } - lc = type.toLowerCase(); - el = UI.checkbox(lc, type + " Tyme", false); - el.title = type + " Tyme"; - this.nodes[lc] = el.firstElementChild; - if (Conf[lc]) { - this.set(lc, true); - } - $.on(this.nodes[lc], 'change', this.toggle.bind(this, lc)); - Header.menu.addEntry({ - el: el, - order: 97 - }); - indicator = $.el('span', { - className: 'indicator', - textContent: type[0], - title: type + " Tyme active" - }); - $.on(indicator, 'click', function() { - var check; - check = $.getOwn(FappeTyme.nodes, this.parentNode.id.replace('shortcut-', '')); - check.checked = !check.checked; - return $.event('change', null, check); - }); - Header.addShortcut(lc, indicator, 410); - } - if (Conf['Werk Tyme']) { - $.sync('werk', this.set.bind(this, 'werk')); - } - Callbacks.Post.push({ - name: 'Fappe Tyme', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Werk Tyme', - cb: this.catalogNode - }); - }, - node: function() { - return this.nodes.root.classList.toggle('noFile', !this.files.length); - }, - catalogNode: function() { - var file, filename; - file = this.thread.OP.files[0]; - if (!file) { - return; - } - filename = $.el('div', { - textContent: file.name, - className: 'werkTyme-filename' - }); - return $.add(this.nodes.thumb.parentNode, filename); - }, - set: function(type, enabled) { - this.enabled[type] = this.nodes[type].checked = enabled; - return $[(enabled ? 'add' : 'rm') + "Class"](doc, type + "Tyme"); - }, - toggle: function(type) { - this.set(type, !this.enabled[type]); - if (type === 'werk') { - return $.cb.checked.call(this.nodes[type]); - } - } - }; - - return FappeTyme; - -}).call(this); - -Gallery = (function() { - var Gallery; - - Gallery = { - init: function() { - var el, ref; - if (!(this.enabled = Conf['Gallery'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.delay = Conf['Slide Delay']; - el = $.el('a', { - href: 'javascript:;', - title: 'Gallery', - className: 'fa fa-picture-o', - textContent: 'Gallery' - }); - $.on(el, 'click', this.cb.toggle); - Header.addShortcut('gallery', el, 530); - return Callbacks.Post.push({ - name: 'Gallery', - cb: this.node - }); - }, - node: function() { - var file, i, len, ref, results; - ref = this.files; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (!file.thumb) { - continue; - } - if (Gallery.nodes) { - Gallery.generateThumb(this, file); - Gallery.nodes.total.textContent = Gallery.images.length; - } - if (!(Conf['Image Expansion'] || (g.SITE.software === 'tinyboard' && Main.jsEnabled))) { - results.push($.on(file.thumbLink, 'click', Gallery.cb.image)); - } else { - results.push(void 0); - } - } - return results; - }, - build: function(image) { - var candidate, cb, dialog, entry, file, i, j, k, key, len, len1, len2, menuButton, nodes, post, postThumb, ref, ref1, ref2, ref3, thumb, value; - cb = Gallery.cb; - if (Conf['Fullscreen Gallery']) { - $.one(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', function() { - return $.on(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', cb.close); - }); - if (typeof doc.mozRequestFullScreen === "function") { - doc.mozRequestFullScreen(); - } - if (typeof doc.webkitRequestFullScreen === "function") { - doc.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); - } - } - Gallery.images = []; - nodes = Gallery.nodes = {}; - Gallery.fileIDs = $.dict(); - Gallery.slideshow = false; - nodes.el = dialog = $.el('div', { - id: 'a-gallery' - }); - $.extend(dialog, {innerHTML: "
      ×
      /
      "}); - ref = { - buttons: '.gal-buttons', - frame: '.gal-image', - name: '.gal-name', - count: '.count', - total: '.total', - sauce: '.gal-sauce', - thumbs: '.gal-thumbnails', - next: '.gal-image a', - current: '.gal-image img' - }; - for (key in ref) { - value = ref[key]; - nodes[key] = $(value, dialog); - } - menuButton = $('.menu-button', dialog); - nodes.menu = new UI.Menu('gallery'); - $.on(nodes.frame, 'click', cb.blank); - if (Conf['Mouse Wheel Volume']) { - $.on(nodes.frame, 'wheel', Volume.wheel); - } - $.on(nodes.next, 'click', cb.click); - $.on(nodes.name, 'click', ImageCommon.download); - $.on($('.gal-prev', dialog), 'click', cb.prev); - $.on($('.gal-next', dialog), 'click', cb.next); - $.on($('.gal-start', dialog), 'click', cb.start); - $.on($('.gal-stop', dialog), 'click', cb.stop); - $.on($('.gal-close', dialog), 'click', cb.close); - $.on(menuButton, 'click', function(e) { - return nodes.menu.toggle(e, this, g); - }); - ref1 = Gallery.menu.createSubEntries(); - for (i = 0, len = ref1.length; i < len; i++) { - entry = ref1[i]; - entry.order = 0; - nodes.menu.addEntry(entry); - } - $.on(d, 'keydown', cb.keybinds); - if (Conf['Keybinds']) { - $.off(d, 'keydown', Keybinds.keydown); - } - $.on(window, 'resize', Gallery.cb.setHeight); - ref2 = $$(g.SITE.selectors.file.thumb); - for (j = 0, len1 = ref2.length; j < len1; j++) { - postThumb = ref2[j]; - if (!(post = Get.postFromNode(postThumb))) { - continue; - } - ref3 = post.files; - for (k = 0, len2 = ref3.length; k < len2; k++) { - file = ref3[k]; - if (!file.thumb) { - continue; - } - Gallery.generateThumb(post, file); - if (!image && Gallery.fileIDs[post.fullID + "." + file.index]) { - candidate = file.thumbLink; - if (Header.getTopOf(candidate) + candidate.getBoundingClientRect().height >= 0) { - image = candidate; - } - } - } - } - $.addClass(doc, 'gallery-open'); - $.add(d.body, dialog); - nodes.thumbs.scrollTop = 0; - nodes.current.parentElement.scrollTop = 0; - if (image) { - thumb = $("[href='" + image.href + "']", nodes.thumbs); - } - thumb || (thumb = Gallery.images[Gallery.images.length - 1]); - if (thumb) { - Gallery.open(thumb); - } - doc.style.overflow = 'hidden'; - return nodes.total.textContent = Gallery.images.length; - }, - generateThumb: function(post, file) { - var thumb, thumbImg; - if (post.isClone || post.isHidden) { - return; - } - if (!(file && file.thumb && (file.isImage || file.isVideo || Conf['PDF in Gallery']))) { - return; - } - if (Gallery.fileIDs[post.fullID + "." + file.index]) { - return; - } - Gallery.fileIDs[post.fullID + "." + file.index] = true; - thumb = $.el('a', { - className: 'gal-thumb', - href: file.url, - target: '_blank', - title: file.name - }); - thumb.dataset.id = Gallery.images.length; - thumb.dataset.post = post.fullID; - thumb.dataset.file = file.index; - thumbImg = file.thumb.cloneNode(false); - thumbImg.style.cssText = ''; - $.add(thumb, thumbImg); - $.on(thumb, 'click', Gallery.cb.open); - Gallery.images.push(thumb); - return $.add(Gallery.nodes.thumbs, thumb); - }, - load: function(thumb, errorCB) { - var elType, ext, file; - ext = thumb.href.match(/\w*$/); - elType = $.getOwn({ - 'webm': 'video', - 'mp4': 'video', - 'ogv': 'video', - 'pdf': 'iframe' - }, ext) || 'img'; - file = $.el(elType); - $.extend(file.dataset, thumb.dataset); - $.on(file, 'error', errorCB); - file.src = thumb.href; - return file; - }, - open: function(thumb) { - var el, file, i, len, link, newID, node, nodes, oldID, post, ref, ref1, sauces; - nodes = Gallery.nodes; - oldID = +nodes.current.dataset.id; - newID = +thumb.dataset.id; - if (el = Gallery.images[oldID]) { - $.rmClass(el, 'gal-highlight'); - } - $.addClass(thumb, 'gal-highlight'); - nodes.thumbs.scrollTop = thumb.offsetTop + thumb.offsetHeight / 2 - nodes.thumbs.clientHeight / 2; - if (((ref = Gallery.cache) != null ? ref.dataset.id : void 0) === '' + newID) { - file = Gallery.cache; - $.off(file, 'error', Gallery.cacheError); - $.on(file, 'error', Gallery.error); - } else { - file = Gallery.load(thumb, Gallery.error); - } - $.off(nodes.current, 'error', Gallery.error); - ImageCommon.pause(nodes.current); - $.replace(nodes.current, file); - nodes.current = file; - if (file.nodeName === 'VIDEO') { - file.loop = true; - Volume.setup(file); - if (Conf['Autoplay']) { - file.play(); - } - if (Conf['Show Controls']) { - ImageCommon.addControls(file); - } - } - doc.classList.toggle('gal-pdf', file.nodeName === 'IFRAME'); - Gallery.cb.setHeight(); - nodes.count.textContent = +thumb.dataset.id + 1; - nodes.name.download = nodes.name.textContent = thumb.title; - nodes.name.href = thumb.href; - nodes.frame.scrollTop = 0; - nodes.next.focus(); - $.rmAll(nodes.sauce); - if (Conf['Sauce'] && Sauce.links && (post = g.posts.get(file.dataset.post))) { - sauces = []; - ref1 = Sauce.links; - for (i = 0, len = ref1.length; i < len; i++) { - link = ref1[i]; - if ((node = Sauce.createSauceLink(link, post, post.files[+file.dataset.file]))) { - sauces.push($.tn(' '), node); - } - } - $.add(nodes.sauce, sauces); - } - if (Gallery.slideshow && (newID > oldID || (oldID === Gallery.images.length - 1 && newID === 0))) { - Gallery.setupTimer(); - } else { - Gallery.cb.stop(); - } - if (Conf['Scroll to Post'] && (post = g.posts.get(file.dataset.post))) { - Header.scrollTo(post.nodes.root); - } - if (isNaN(oldID) || newID === (oldID + 1) % Gallery.images.length) { - return Gallery.cache = Gallery.load(Gallery.images[(newID + 1) % Gallery.images.length], Gallery.cacheError); - } - }, - error: function() { - var file, post, ref; - if (((ref = this.error) != null ? ref.code : void 0) === MediaError.MEDIA_ERR_DECODE) { - return new Notice('error', 'Corrupt or unplayable video', 30); - } - if (ImageCommon.isFromArchive(this)) { - return; - } - post = g.posts.get(this.dataset.post); - file = post.files[+this.dataset.file]; - return ImageCommon.error(this, post, file, null, (function(_this) { - return function(url) { - if (!url) { - return; - } - Gallery.images[+_this.dataset.id].href = url; - if (Gallery.nodes.current === _this) { - return _this.src = url; - } - }; - })(this)); - }, - cacheError: function() { - return delete Gallery.cache; - }, - cleanupTimer: function() { - var current; - clearTimeout(Gallery.timeoutID); - current = Gallery.nodes.current; - $.off(current, 'canplaythrough load', Gallery.startTimer); - return $.off(current, 'ended', Gallery.cb.next); - }, - startTimer: function() { - return Gallery.timeoutID = setTimeout(Gallery.checkTimer, Gallery.delay * $.SECOND); - }, - setupTimer: function() { - var current, isVideo; - Gallery.cleanupTimer(); - current = Gallery.nodes.current; - isVideo = current.nodeName === 'VIDEO'; - if (isVideo) { - current.play(); - } - if ((isVideo ? current.readyState >= 4 : current.complete) || current.nodeName === 'IFRAME') { - return Gallery.startTimer(); - } else { - return $.on(current, (isVideo ? 'canplaythrough' : 'load'), Gallery.startTimer); - } - }, - checkTimer: function() { - var current; - current = Gallery.nodes.current; - if (current.nodeName === 'VIDEO' && !current.paused) { - $.on(current, 'ended', Gallery.cb.next); - return current.loop = false; - } else { - return Gallery.cb.next(); - } - }, - cb: { - keybinds: function(e) { - var cb, key; - if (!(key = Keybinds.keyCode(e))) { - return; - } - cb = (function() { - switch (key) { - case Conf['Close']: - case Conf['Open Gallery']: - return Gallery.cb.close; - case Conf['Next Gallery Image']: - return Gallery.cb.next; - case Conf['Advance Gallery']: - return Gallery.cb.advance; - case Conf['Previous Gallery Image']: - return Gallery.cb.prev; - case Conf['Pause']: - return Gallery.cb.pause; - case Conf['Slideshow']: - return Gallery.cb.toggleSlideshow; - case Conf['Rotate image anticlockwise']: - return Gallery.cb.rotateLeft; - case Conf['Rotate image clockwise']: - return Gallery.cb.rotateRight; - case Conf['Download Gallery Image']: - return Gallery.cb.download; - } - })(); - if (!cb) { - return; - } - e.stopPropagation(); - e.preventDefault(); - return cb(); - }, - open: function(e) { - if (e) { - e.preventDefault(); - } - if (this) { - return Gallery.open(this); - } - }, - image: function(e) { - e.preventDefault(); - e.stopPropagation(); - return Gallery.build(this); - }, - prev: function() { - return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id - 1] || Gallery.images[Gallery.images.length - 1]); - }, - next: function() { - return Gallery.cb.open.call(Gallery.images[+Gallery.nodes.current.dataset.id + 1] || Gallery.images[0]); - }, - click: function(e) { - if (ImageCommon.onControls(e)) { - return; - } - e.preventDefault(); - return Gallery.cb.advance(); - }, - advance: function() { - if (!Conf['Autoplay'] && Gallery.nodes.current.paused) { - return Gallery.nodes.current.play(); - } else { - return Gallery.cb.next(); - } - }, - toggle: function() { - return (Gallery.nodes ? Gallery.cb.close : Gallery.build)(); - }, - blank: function(e) { - if (e.target === this) { - return Gallery.cb.close(); - } - }, - toggleSlideshow: function() { - return Gallery.cb[Gallery.slideshow ? 'stop' : 'start'](); - }, - download: function() { - var name; - name = $('.gal-name'); - return name.click(); - }, - pause: function() { - var current; - Gallery.cb.stop(); - current = Gallery.nodes.current; - if (current.nodeName === 'VIDEO') { - return current[current.paused ? 'play' : 'pause'](); - } - }, - start: function() { - $.addClass(Gallery.nodes.buttons, 'gal-playing'); - Gallery.slideshow = true; - return Gallery.setupTimer(); - }, - stop: function() { - var current; - if (!Gallery.slideshow) { - return; - } - Gallery.cleanupTimer(); - current = Gallery.nodes.current; - if (current.nodeName === 'VIDEO') { - current.loop = true; - } - $.rmClass(Gallery.nodes.buttons, 'gal-playing'); - return Gallery.slideshow = false; - }, - rotateLeft: function() { - return Gallery.cb.rotate(270); - }, - rotateRight: function() { - return Gallery.cb.rotate(90); - }, - rotate: $.debounce(100, function(delta) { - var current; - current = Gallery.nodes.current; - if (current.nodeName === 'IFRAME') { - return; - } - current.dataRotate = ((current.dataRotate || 0) + delta) % 360; - current.style.transform = "rotate(" + current.dataRotate + "deg)"; - return Gallery.cb.setHeight(); - }), - close: function() { - $.off(Gallery.nodes.current, 'error', Gallery.error); - ImageCommon.pause(Gallery.nodes.current); - $.rm(Gallery.nodes.el); - $.rmClass(doc, 'gallery-open'); - if (Conf['Fullscreen Gallery']) { - $.off(d, 'fullscreenchange mozfullscreenchange webkitfullscreenchange', Gallery.cb.close); - if (typeof d.mozCancelFullScreen === "function") { - d.mozCancelFullScreen(); - } - if (typeof d.webkitExitFullscreen === "function") { - d.webkitExitFullscreen(); - } - } - delete Gallery.nodes; - delete Gallery.fileIDs; - doc.style.overflow = ''; - $.off(d, 'keydown', Gallery.cb.keybinds); - if (Conf['Keybinds']) { - $.on(d, 'keydown', Keybinds.keydown); - } - $.off(window, 'resize', Gallery.cb.setHeight); - return clearTimeout(Gallery.timeoutID); - }, - setFitness: function() { - return (this.checked ? $.addClass : $.rmClass)(doc, "gal-" + (this.name.toLowerCase().replace(/\s+/g, '-'))); - }, - setHeight: $.debounce(100, function() { - var containerHeight, containerWidth, current, dim, frame, height, margin, minHeight, ref, ref1, ref2, ref3, style, width; - ref = Gallery.nodes, current = ref.current, frame = ref.frame; - style = current.style; - if (Conf['Stretch to Fit'] && (dim = (ref1 = g.posts.get(current.dataset.post)) != null ? ref1.files[+current.dataset.file].dimensions : void 0)) { - ref2 = dim.split('x'), width = ref2[0], height = ref2[1]; - containerWidth = frame.clientWidth; - containerHeight = doc.clientHeight - 25; - if ((current.dataRotate || 0) % 180 === 90) { - ref3 = [containerHeight, containerWidth], containerWidth = ref3[0], containerHeight = ref3[1]; - } - minHeight = Math.min(containerHeight, height / width * containerWidth); - style.minHeight = minHeight + 'px'; - style.minWidth = (width / height * minHeight) + 'px'; - } else { - style.minHeight = style.minWidth = ''; - } - if ((current.dataRotate || 0) % 180 === 90) { - style.maxWidth = Conf['Fit Height'] ? (doc.clientHeight - 25) + "px" : 'none'; - style.maxHeight = Conf['Fit Width'] ? frame.clientWidth + "px" : 'none'; - margin = (current.clientWidth - current.clientHeight) / 2; - return style.margin = margin + "px " + (-margin) + "px"; - } else { - return style.maxWidth = style.maxHeight = style.margin = ''; - } - }), - setDelay: function() { - return Gallery.delay = +this.value; - } - }, - menu: { - init: function() { - var el; - if (!Gallery.enabled) { - return; - } - el = $.el('span', { - textContent: 'Gallery', - className: 'gallery-link' - }); - return Header.menu.addEntry({ - el: el, - order: 105, - subEntries: Gallery.menu.createSubEntries() - }); - }, - createSubEntry: function(name) { - var input, label; - label = UI.checkbox(name, name); - input = label.firstElementChild; - if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height') { - $.on(input, 'change', Gallery.cb.setFitness); - } - $.event('change', null, input); - $.on(input, 'change', $.cb.checked); - if (name === 'Hide Thumbnails' || name === 'Fit Width' || name === 'Fit Height' || name === 'Stretch to Fit') { - $.on(input, 'change', Gallery.cb.setHeight); - } - return { - el: label - }; - }, - createSubEntries: function() { - var delayInput, delayLabel, item, subEntries; - subEntries = (function() { - var i, len, ref, results; - ref = ['Hide Thumbnails', 'Fit Width', 'Fit Height', 'Stretch to Fit', 'Scroll to Post']; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - item = ref[i]; - results.push(Gallery.menu.createSubEntry(item)); - } - return results; - })(); - delayLabel = $.el('label', {innerHTML: "Slide Delay: "}); - delayInput = delayLabel.firstElementChild; - delayInput.value = Gallery.delay; - $.on(delayInput, 'change', Gallery.cb.setDelay); - $.on(delayInput, 'change', $.cb.value); - subEntries.push({ - el: delayLabel - }); - return subEntries; - } - } - }; - - return Gallery; - -}).call(this); - -ImageCommon = (function() { - var ImageCommon, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - ImageCommon = { - pause: function(video) { - if (video.nodeName !== 'VIDEO') { - return; - } - video.pause(); - $.off(video, 'volumechange', Volume.change); - return video.muted = true; - }, - rewind: function(el) { - if (el.nodeName === 'VIDEO') { - if (el.readyState >= el.HAVE_METADATA) { - return el.currentTime = 0; - } - } else if (/\.gif$/.test(el.src)) { - return $.queueTask(function() { - return el.src = el.src; - }); - } - }, - pushCache: function(el) { - ImageCommon.cache = el; - return $.on(el, 'error', ImageCommon.cacheError); - }, - popCache: function() { - var el; - el = ImageCommon.cache; - $.off(el, 'error', ImageCommon.cacheError); - delete ImageCommon.cache; - return el; - }, - cacheError: function() { - if (ImageCommon.cache === this) { - return delete ImageCommon.cache; - } - }, - decodeError: function(file, fileObj) { - var message, ref; - if (((ref = file.error) != null ? ref.code : void 0) !== MediaError.MEDIA_ERR_DECODE) { - return false; - } - if (!(message = $('.warning', fileObj.thumb.parentNode))) { - message = $.el('div', { - className: 'warning' - }); - $.after(fileObj.thumb, message); - } - message.textContent = 'Error: Corrupt or unplayable video'; - return true; - }, - isFromArchive: function(file) { - return g.SITE.software === 'yotsuba' && !ImageHost.test(file.src.split('/')[2]); - }, - error: function(file, post, fileObj, delay, cb) { - var base, parseJSON, redirect, src, threadJSON, timeoutID, url; - src = fileObj.url.split('/'); - url = null; - if (g.SITE.software === 'yotsuba' && Conf['404 Redirect']) { - url = Redirect.to('file', { - boardID: post.board.ID, - filename: src[src.length - 1] - }); - } - if (!(url && Redirect.securityCheck(url))) { - url = null; - } - if ((post.isDead || fileObj.isDead) && !ImageCommon.isFromArchive(file)) { - return cb(url); - } - if (delay != null) { - timeoutID = setTimeout((function() { - return cb(url); - }), delay); - } - if (post.isDead || fileObj.isDead) { - return; - } - redirect = function() { - if (!ImageCommon.isFromArchive(file)) { - if (delay != null) { - clearTimeout(timeoutID); - } - return cb(url); - } - }; - threadJSON = typeof (base = g.SITE.urls).threadJSON === "function" ? base.threadJSON(post) : void 0; - if (!threadJSON) { - return; - } - parseJSON = function(isArchiveURL) { - var archivedThreadJSON, base1, i, len, postObj, ref, ref1; - if (this.status === 404) { - if (!isArchiveURL && (archivedThreadJSON = typeof (base1 = g.SITE.urls).archivedThreadJSON === "function" ? base1.archivedThreadJSON(post) : void 0)) { - $.ajax(archivedThreadJSON, { - onloadend: function() { - return parseJSON.call(this, true); - } - }); - } else { - post.kill(!post.isClone, fileObj.index); - } - } - if (this.status !== 200) { - return redirect(); - } - ref = this.response.posts; - for (i = 0, len = ref.length; i < len; i++) { - postObj = ref[i]; - if (postObj.no === post.ID) { - break; - } - } - if (postObj.no !== post.ID) { - post.kill(); - return redirect(); - } else if (ref1 = fileObj.docIndex, indexOf.call(g.SITE.Build.parseJSON(postObj, post.board).filesDeleted, ref1) >= 0) { - post.kill(true); - return redirect(); - } else { - return url = fileObj.url; - } - }; - return $.ajax(threadJSON, { - onloadend: function() { - return parseJSON.call(this); - } - }); - }, - addControls: function(video) { - var handler; - handler = function() { - var t; - $.off(video, 'mouseover', handler); - t = new Date().getTime(); - return $.asap((function() { - return $.engine !== 'gecko' || (video.readyState >= 3 && video.currentTime <= Math.max(0.1, video.duration - 0.5)) || new Date().getTime() >= t + 1000; - }), function() { - return video.controls = true; - }); - }; - return $.on(video, 'mouseover', handler); - }, - onControls: function(e) { - return (Conf['Show Controls'] && Conf['Click Passthrough'] && e.target.nodeName === 'VIDEO') || (e.target.controls && e.target.getBoundingClientRect().bottom - e.clientY < 35); - }, - download: function(e) { - var download, href, ref; - if (this.protocol === 'blob:') { - return true; - } - e.preventDefault(); - ref = this, href = ref.href, download = ref.download; - return CrossOrigin.file(href, function(blob) { - var a; - if (blob) { - a = $.el('a', { - href: URL.createObjectURL(blob), - download: download, - hidden: true - }); - $.add(d.body, a); - a.click(); - return $.rm(a); - } else { - return new Notice('warning', "Could not download " + href, 20); - } - }); - } - }; - - return ImageCommon; - -}).call(this); - -ImageExpand = (function() { - var ImageExpand, - slice = [].slice; - - ImageExpand = { - init: function() { - var ref; - if (!(this.enabled = Conf['Image Expansion'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.EAI = $.el('a', { - className: 'expand-all-shortcut fa fa-expand', - textContent: 'EAI', - title: 'Expand All Images', - href: 'javascript:;' - }); - $.on(this.EAI, 'click', this.cb.toggleAll); - Header.addShortcut('expand-all', this.EAI, 520); - $.on(d, 'scroll visibilitychange', this.cb.playVideos); - this.videoControls = $.el('span', { - className: 'video-controls' - }); - $.extend(this.videoControls, {innerHTML: " contract"}); - return Callbacks.Post.push({ - name: 'Image Expansion', - cb: this.node - }); - }, - node: function() { - var ref; - if (!(this.file && (this.file.isImage || this.file.isVideo))) { - return; - } - $.on(this.file.thumbLink, 'click', ImageExpand.cb.toggle); - if (this.isClone) { - if (this.file.isExpanding) { - ImageExpand.contract(this); - return ImageExpand.expand(this); - } else if (this.file.isExpanded && this.file.isVideo) { - Volume.setup(this.file.fullImage); - ImageExpand.setupVideoCB(this); - return ImageExpand.setupVideo(this, !((ref = this.origin.file.fullImage) != null ? ref.paused : void 0) || this.origin.file.wasPlaying, this.file.fullImage.controls); - } - } else if (ImageExpand.on && !this.isHidden && !this.isFetchedQuote && (Conf['Expand spoilers'] || !this.file.isSpoiler) && (Conf['Expand videos'] || !this.file.isVideo)) { - return ImageExpand.expand(this); - } - }, - cb: { - toggle: function(e) { - var file, post, ref; - if ($.modifiedClick(e)) { - return; - } - post = Get.postFromNode(this); - file = post.file; - if (file.isExpanded && ImageCommon.onControls(e)) { - return; - } - e.preventDefault(); - if (!Conf['Autoplay'] && ((ref = file.fullImage) != null ? ref.paused : void 0)) { - return file.fullImage.play(); - } else { - return ImageExpand.toggle(post); - } - }, - toggleAll: function() { - var func, threadRoot, toggle; - $.event('CloseMenu'); - threadRoot = Nav.getThread(); - toggle = function(post) { - var file; - file = post.file; - if (!(file && (file.isImage || file.isVideo) && doc.contains(post.nodes.root))) { - return; - } - if (ImageExpand.on && (!Conf['Expand spoilers'] && file.isSpoiler || !Conf['Expand videos'] && file.isVideo || Conf['Expand from here'] && Header.getTopOf(file.thumb) < 0 || Conf['Expand thread only'] && g.VIEW === 'index' && !(threadRoot != null ? threadRoot.contains(file.thumb) : void 0))) { - return; - } - return $.queueTask(func, post); - }; - if (ImageExpand.on = $.hasClass(ImageExpand.EAI, 'expand-all-shortcut')) { - ImageExpand.EAI.className = 'contract-all-shortcut fa fa-compress'; - ImageExpand.EAI.title = 'Contract All Images'; - func = ImageExpand.expand; - } else { - ImageExpand.EAI.className = 'expand-all-shortcut fa fa-expand'; - ImageExpand.EAI.title = 'Expand All Images'; - func = ImageExpand.contract; - } - return g.posts.forEach(function(post) { - var i, len, ref; - ref = [post].concat(slice.call(post.clones)); - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - toggle(post); - } - }); - }, - playVideos: function() { - return g.posts.forEach(function(post) { - var file, i, len, ref, video, visible; - ref = [post].concat(slice.call(post.clones)); - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - file = post.file; - if (!(file && file.isVideo && file.isExpanded)) { - continue; - } - video = file.fullImage; - visible = ($.hasAudio(video) && !video.muted) || Header.isNodeVisible(video); - if (visible && file.wasPlaying) { - delete file.wasPlaying; - video.play(); - } else if (!visible && !video.paused) { - file.wasPlaying = true; - video.pause(); - } - } - }); - }, - setFitness: function() { - return $[this.checked ? 'addClass' : 'rmClass'](doc, this.name.toLowerCase().replace(/\s+/g, '-')); - } - }, - toggle: function(post) { - var next; - if (!(post.file.isExpanding || post.file.isExpanded)) { - post.file.scrollIntoView = Conf['Scroll into view']; - ImageExpand.expand(post); - return; - } - ImageExpand.contract(post); - if (Conf['Advance on contract']) { - next = post.nodes.root; - while (next = $.x("following::div[contains(@class,'postContainer')][1]", next)) { - if (!($('.stub', next) || next.offsetHeight === 0)) { - break; - } - } - if (next) { - return Header.scrollTo(next); - } - } - }, - contract: function(post) { - var bottom, cb, el, eventName, file, i, len, oldHeight, ref, ref1, scrollY, top, x; - file = post.file; - if (el = file.fullImage) { - top = Header.getTopOf(el); - bottom = top + el.getBoundingClientRect().height; - oldHeight = d.body.clientHeight; - scrollY = window.scrollY; - } - $.rmClass(post.nodes.root, 'expanded-image'); - $.rmClass(file.thumb, 'expanding'); - $.rm(file.videoControls); - file.thumbLink.href = file.url; - file.thumbLink.target = '_blank'; - ref = ['isExpanding', 'isExpanded', 'videoControls', 'wasPlaying', 'scrollIntoView']; - for (i = 0, len = ref.length; i < len; i++) { - x = ref[i]; - delete file[x]; - } - if (!el) { - return; - } - if (doc.contains(el)) { - if (bottom <= 0) { - window.scrollBy(0, scrollY - window.scrollY + d.body.clientHeight - oldHeight); - } else { - Header.scrollToIfNeeded(post.nodes.root); - } - if (window.scrollX > 0) { - window.scrollBy(-window.scrollX, 0); - } - } - $.off(el, 'error', ImageExpand.error); - ImageCommon.pushCache(el); - if (file.isVideo) { - ImageCommon.pause(el); - ref1 = ImageExpand.videoCB; - for (eventName in ref1) { - cb = ref1[eventName]; - $.off(el, eventName, cb); - } - } - if (Conf['Restart when Opened']) { - ImageCommon.rewind(file.thumb); - } - delete file.fullImage; - return $.queueTask(function() { - if (file.isExpanding || file.isExpanded) { - return; - } - $.rmClass(el, 'full-image'); - if (el.id) { - return; - } - return $.rm(el); - }); - }, - expand: function(post, src) { - var el, file, isVideo, ref, thumb, thumbLink; - file = post.file; - thumb = file.thumb, thumbLink = file.thumbLink, isVideo = file.isVideo; - if (post.isHidden || file.isExpanding || file.isExpanded) { - return; - } - $.addClass(thumb, 'expanding'); - file.isExpanding = true; - if (file.fullImage) { - el = file.fullImage; - } else if (((ref = ImageCommon.cache) != null ? ref.dataset.fileID : void 0) === (post.fullID + "." + file.index)) { - el = file.fullImage = ImageCommon.popCache(); - $.on(el, 'error', ImageExpand.error); - if (Conf['Restart when Opened'] && el.id !== 'ihover') { - ImageCommon.rewind(el); - } - el.removeAttribute('id'); - } else { - el = file.fullImage = $.el((isVideo ? 'video' : 'img')); - el.dataset.fileID = post.fullID + "." + file.index; - $.on(el, 'error', ImageExpand.error); - el.src = src || file.url; - } - el.className = 'full-image'; - $.after(thumb, el); - if (isVideo) { - if (!file.videoControls) { - file.videoControls = ImageExpand.videoControls.cloneNode(true); - $.add(file.text, file.videoControls); - } - thumbLink.removeAttribute('href'); - thumbLink.removeAttribute('target'); - el.loop = true; - Volume.setup(el); - ImageExpand.setupVideoCB(post); - } - if (!isVideo) { - return $.asap((function() { - return el.naturalHeight; - }), function() { - return ImageExpand.completeExpand(post); - }); - } else if (el.readyState >= el.HAVE_METADATA) { - return ImageExpand.completeExpand(post); - } else { - return $.on(el, 'loadedmetadata', function() { - return ImageExpand.completeExpand(post); - }); - } - }, - completeExpand: function(post) { - var bottom, file, imageBottom, oldHeight, scrollY; - file = post.file; - if (!file.isExpanding) { - return; - } - bottom = Header.getTopOf(file.thumb) + file.thumb.getBoundingClientRect().height; - oldHeight = d.body.clientHeight; - scrollY = window.scrollY; - $.addClass(post.nodes.root, 'expanded-image'); - $.rmClass(file.thumb, 'expanding'); - file.isExpanded = true; - delete file.isExpanding; - if (doc.contains(post.nodes.root) && bottom <= 0) { - window.scrollBy(0, scrollY - window.scrollY + d.body.clientHeight - oldHeight); - } - if (file.scrollIntoView) { - delete file.scrollIntoView; - imageBottom = Math.min(doc.clientHeight - file.fullImage.getBoundingClientRect().bottom - 25, Header.getBottomOf(file.fullImage)); - if (imageBottom < 0) { - window.scrollBy(0, Math.min(-imageBottom, Header.getTopOf(file.fullImage))); - } - } - if (file.isVideo) { - return ImageExpand.setupVideo(post, Conf['Autoplay'], Conf['Show Controls']); - } - }, - setupVideo: function(post, playing, controls) { - var fullImage; - fullImage = post.file.fullImage; - if (!playing) { - fullImage.controls = controls; - return; - } - fullImage.controls = false; - $.asap((function() { - return doc.contains(fullImage); - }), function() { - if (!d.hidden && Header.isNodeVisible(fullImage)) { - return fullImage.play(); - } else { - return post.file.wasPlaying = true; - } - }); - if (controls) { - return ImageCommon.addControls(fullImage); - } - }, - videoCB: (function() { - var mousedown; - mousedown = false; - return { - mouseover: function() { - return mousedown = false; - }, - mousedown: function(e) { - if (e.button === 0) { - return mousedown = true; - } - }, - mouseup: function(e) { - if (e.button === 0) { - return mousedown = false; - } - }, - mouseout: function(e) { - if (((e.buttons & 1) || mousedown) && e.clientX <= this.getBoundingClientRect().left) { - return ImageExpand.toggle(Get.postFromNode(this)); - } - } - }; - })(), - setupVideoCB: function(post) { - var cb, eventName, ref; - ref = ImageExpand.videoCB; - for (eventName in ref) { - cb = ref[eventName]; - $.on(post.file.fullImage, eventName, cb); - } - if (post.file.videoControls) { - return $.on(post.file.videoControls.firstElementChild, 'click', function() { - return ImageExpand.toggle(post); - }); - } - }, - error: function() { - var post; - post = Get.postFromNode(this); - $.rm(this); - delete post.file.fullImage; - if (!(post.file.isExpanding || post.file.isExpanded)) { - return; - } - if (ImageCommon.decodeError(this, post.file)) { - return ImageExpand.contract(post); - } - if (ImageCommon.isFromArchive(this)) { - return ImageExpand.contract(post); - } - return ImageCommon.error(this, post, post.file, 10 * $.SECOND, function(URL) { - if (post.file.isExpanding || post.file.isExpanded) { - ImageExpand.contract(post); - if (URL) { - return ImageExpand.expand(post, URL); - } - } - }); - }, - menu: { - init: function() { - var conf, createSubEntry, el, name, ref, subEntries; - if (!ImageExpand.enabled) { - return; - } - el = $.el('span', { - textContent: 'Image Expansion', - className: 'image-expansion-link' - }); - createSubEntry = ImageExpand.menu.createSubEntry; - subEntries = []; - ref = Config.imageExpansion; - for (name in ref) { - conf = ref[name]; - subEntries.push(createSubEntry(name, conf[1])); - } - return Header.menu.addEntry({ - el: el, - order: 105, - subEntries: subEntries - }); - }, - createSubEntry: function(name, desc) { - var input, label; - label = UI.checkbox(name, name); - label.title = desc; - input = label.firstElementChild; - if (name === 'Fit width' || name === 'Fit height') { - $.on(input, 'change', ImageExpand.cb.setFitness); - } - $.event('change', null, input); - $.on(input, 'change', $.cb.checked); - return { - el: label - }; - } - } - }; - - return ImageExpand; - -}).call(this); - -ImageHost = (function() { - var ImageHost; - - ImageHost = { - init: function() { - var ref; - if (!((this.useFaster = /\S/.test(Conf['fourchanImageHost'])) && g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - return Callbacks.Post.push({ - name: 'Image Host Rewriting', - cb: this.node - }); - }, - suggestions: ['i.4cdn.org', 'is2.4chan.org'], - host: function() { - return Conf['fourchanImageHost'].trim() || 'i.4cdn.org'; - }, - flashHost: function() { - return 'i.4cdn.org'; - }, - thumbHost: function() { - return 'i.4cdn.org'; - }, - test: function(hostname) { - return hostname === 'i.4cdn.org' || ImageHost.regex.test(hostname); - }, - regex: /^is\d*\.4chan(?:nel)?\.org$/, - node: function() { - var host; - if (this.isClone) { - return; - } - host = ImageHost.host(); - if (this.file && ImageHost.test(this.file.url.split('/')[2]) && !/\.swf$/.test(this.file.url)) { - this.file.link.hostname = host; - if (this.file.thumbLink) { - this.file.thumbLink.hostname = host; - } - this.file.url = this.file.link.href; - } - return ImageHost.fixLinks($$('a', this.nodes.comment)); - }, - fixLinks: function(links) { - var host, i, len, link; - for (i = 0, len = links.length; i < len; i++) { - link = links[i]; - if (!(ImageHost.test(link.hostname) && !/\.swf$/.test(link.pathname))) { - continue; - } - host = ImageHost.host(); - if (link.hostname !== host) { - link.hostname = host; - } - } - } - }; - - return ImageHost; - -}).call(this); - -ImageHover = (function() { - var ImageHover; - - ImageHover = { - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - if (Conf['Image Hover']) { - Callbacks.Post.push({ - name: 'Image Hover', - cb: this.node - }); - } - if (Conf['Image Hover in Catalog']) { - return Callbacks.CatalogThread.push({ - name: 'Image Hover', - cb: this.catalogNode - }); - } - }, - node: function() { - var file, i, len, ref, results; - ref = this.files; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if ((file.isImage || file.isVideo) && file.thumb) { - results.push($.on(file.thumb, 'mouseover', ImageHover.mouseover(this, file))); - } - } - return results; - }, - catalogNode: function() { - var file; - file = this.thread.OP.files[0]; - if (!(file && (file.isImage || file.isVideo))) { - return; - } - return $.on(this.nodes.thumb, 'mouseover', ImageHover.mouseover(this.thread.OP, file)); - }, - mouseover: function(post, file) { - return function(e) { - var base, el, error, height, isVideo, maxHeight, maxWidth, ref, ref1, scale, width, x; - if (!doc.contains(this)) { - return; - } - isVideo = file.isVideo; - if (file.isExpanding || file.isExpanded || (typeof (base = g.SITE).isThumbExpanded === "function" ? base.isThumbExpanded(file) : void 0)) { - return; - } - error = ImageHover.error(post, file); - if (((ref = ImageCommon.cache) != null ? ref.dataset.fileID : void 0) === (post.fullID + "." + file.index)) { - el = ImageCommon.popCache(); - $.on(el, 'error', error); - } else { - el = $.el((isVideo ? 'video' : 'img')); - el.dataset.fileID = post.fullID + "." + file.index; - $.on(el, 'error', error); - el.src = file.url; - } - if (Conf['Restart when Opened']) { - ImageCommon.rewind(el); - ImageCommon.rewind(this); - } - el.id = 'ihover'; - $.add(Header.hover, el); - if (isVideo) { - el.loop = true; - el.controls = false; - Volume.setup(el); - if (Conf['Autoplay']) { - el.play(); - if (this.nodeName === 'VIDEO') { - this.currentTime = el.currentTime; - } - } - } - if (file.dimensions) { - ref1 = (function() { - var i, len, ref1, results; - ref1 = file.dimensions.split('x'); - results = []; - for (i = 0, len = ref1.length; i < len; i++) { - x = ref1[i]; - results.push(+x); - } - return results; - })(), width = ref1[0], height = ref1[1]; - maxWidth = doc.clientWidth; - maxHeight = doc.clientHeight - UI.hover.padding; - scale = Math.min(1, maxWidth / width, maxHeight / height); - width *= scale; - height *= scale; - el.style.maxWidth = width + "px"; - el.style.maxHeight = height + "px"; - } - return UI.hover({ - root: this, - el: el, - latestEvent: e, - endEvents: 'mouseout click', - height: height, - width: width, - noRemove: true, - cb: function() { - $.off(el, 'error', error); - ImageCommon.pushCache(el); - ImageCommon.pause(el); - $.rm(el); - return el.removeAttribute('style'); - } - }); - }; - }, - error: function(post, file) { - return function() { - if (ImageCommon.decodeError(this, file)) { - return; - } - return ImageCommon.error(this, post, file, 3 * $.SECOND, (function(_this) { - return function(URL) { - if (URL) { - return _this.src = URL + (_this.src === URL ? '?' + Date.now() : ''); - } else { - return $.rm(_this); - } - }; - })(this)); - }; - } - }; - - return ImageHover; - -}).call(this); - -ImageLoader = (function() { - var ImageLoader, - slice = [].slice; - - ImageLoader = { - init: function() { - var el, ref, ref1, replace; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') { - return; - } - replace = Conf['Replace JPG'] || Conf['Replace PNG'] || Conf['Replace GIF'] || Conf['Replace WEBM']; - if (!(Conf['Image Prefetching'] || replace)) { - return; - } - Callbacks.Post.push({ - name: 'Image Replace', - cb: this.node - }); - $.on(d, 'PostsInserted', function() { - if (ImageLoader.prefetchEnabled || replace) { - return g.posts.forEach(ImageLoader.prefetchAll); - } - }); - if (Conf['Replace WEBM']) { - $.on(d, 'scroll visibilitychange 4chanXInitFinished PostsInserted', this.playVideos); - } - if (!(Conf['Image Prefetching'] && ((ref1 = g.VIEW) === 'index' || ref1 === 'thread'))) { - return; - } - el = $.el('a', { - href: 'javascript:;', - title: 'Prefetch Images', - className: 'fa fa-bolt disabled', - textContent: 'Prefetch' - }); - $.on(el, 'click', this.toggle); - return Header.addShortcut('prefetch', el, 525); - }, - node: function() { - var file, i, len, ref; - if (this.isClone) { - return; - } - ref = this.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (Conf['Replace WEBM'] && file.isVideo) { - ImageLoader.replaceVideo(this, file); - } - ImageLoader.prefetch(this, file); - } - }, - replaceVideo: function(post, file) { - var attr, i, len, ref, thumb, video; - thumb = file.thumb; - video = $.el('video', { - preload: 'none', - loop: true, - muted: true, - poster: thumb.src || thumb.dataset.src, - textContent: thumb.alt, - className: thumb.className - }); - video.setAttribute('muted', 'muted'); - video.dataset.md5 = thumb.dataset.md5; - ref = ['height', 'width', 'maxHeight', 'maxWidth']; - for (i = 0, len = ref.length; i < len; i++) { - attr = ref[i]; - video.style[attr] = thumb.style[attr]; - } - video.src = file.url; - $.replace(thumb, video); - file.thumb = video; - return file.videoThumb = true; - }, - prefetch: function(post, file) { - var clone, el, i, isImage, isVideo, len, ref, ref1, replace, thumb, type, url; - isImage = file.isImage, isVideo = file.isVideo, thumb = file.thumb, url = file.url; - if (file.isPrefetched || !(isImage || isVideo) || post.isHidden || post.thread.isHidden) { - return; - } - if (isVideo) { - type = 'WEBM'; - } else { - type = (ref = url.match(/\.([^.]+)$/)) != null ? ref[1].toUpperCase() : void 0; - if (type === 'JPEG') { - type = 'JPG'; - } - } - replace = Conf["Replace " + type] && !/spoiler/.test(thumb.src || thumb.dataset.src); - if (!(replace || ImageLoader.prefetchEnabled)) { - return; - } - if ($.hasClass(doc, 'catalog-mode')) { - return; - } - if (![post].concat(slice.call(post.clones)).some(function(clone) { - return doc.contains(clone.nodes.root); - })) { - return; - } - file.isPrefetched = true; - if (file.videoThumb) { - ref1 = post.clones; - for (i = 0, len = ref1.length; i < len; i++) { - clone = ref1[i]; - clone.file.thumb.preload = 'auto'; - } - thumb.preload = 'auto'; - if ($.engine === 'gecko') { - $.on(thumb, 'loadeddata', function() { - return this.removeAttribute('poster'); - }); - } - return; - } - el = $.el(isImage ? 'img' : 'video'); - if (isVideo) { - el.preload = 'auto'; - } - if (replace && isImage) { - $.on(el, 'load', function() { - var j, len1, ref2; - ref2 = post.clones; - for (j = 0, len1 = ref2.length; j < len1; j++) { - clone = ref2[j]; - clone.file.thumb.src = url; - } - return thumb.src = url; - }); - } - return el.src = url; - }, - prefetchAll: function(post) { - var file, i, len, ref; - ref = post.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - ImageLoader.prefetch(post, file); - } - }, - toggle: function() { - ImageLoader.prefetchEnabled = !ImageLoader.prefetchEnabled; - this.classList.toggle('disabled', !ImageLoader.prefetchEnabled); - if (ImageLoader.prefetchEnabled) { - g.posts.forEach(ImageLoader.prefetchAll); - } - }, - playVideos: function() { - var qpClone, ref; - qpClone = (ref = $.id('qp')) != null ? ref.firstElementChild : void 0; - return g.posts.forEach(function(post) { - var file, i, j, len, len1, ref1, ref2, thumb; - ref1 = [post].concat(slice.call(post.clones)); - for (i = 0, len = ref1.length; i < len; i++) { - post = ref1[i]; - ref2 = post.files; - for (j = 0, len1 = ref2.length; j < len1; j++) { - file = ref2[j]; - if (!file.videoThumb) { - continue; - } - thumb = file.thumb; - if (Header.isNodeVisible(thumb) || post.nodes.root === qpClone) { - thumb.play(); - } else { - thumb.pause(); - } - } - } - }); - } - }; - - return ImageLoader; - -}).call(this); - -Metadata = (function() { - var Metadata; - - Metadata = { - init: function() { - var ref; - if (!(Conf['WEBM Metadata'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - return Callbacks.Post.push({ - name: 'WEBM Metadata', - cb: this.node - }); - }, - node: function() { - var el, file, i, j, len1, ref; - ref = this.files; - for (i = j = 0, len1 = ref.length; j < len1; i = ++j) { - file = ref[i]; - if (!(/webm$/i.test(file.url))) { - continue; - } - if (this.isClone) { - el = $('.webm-title', file.text); - } else { - el = $.el('span', { - className: 'webm-title' - }); - el.dataset.index = i; - $.extend(el, {innerHTML: ""}); - $.add(file.text, [$.tn(' '), el]); - } - if (el.children.length === 1) { - $.one(el.lastElementChild, 'mouseover focus', Metadata.load); - } - } - }, - load: function() { - var index; - $.rmClass(this.parentNode, 'error'); - $.addClass(this.parentNode, 'loading'); - index = this.parentNode.dataset.index; - return CrossOrigin.binary(Get.postFromNode(this).files[+index].url, (function(_this) { - return function(data) { - var output, title; - $.rmClass(_this.parentNode, 'loading'); - if (data != null) { - title = Metadata.parse(data); - output = $.el('span', { - textContent: title || '' - }); - if (title == null) { - $.addClass(_this.parentNode, 'not-found'); - } - $.before(_this, output); - _this.parentNode.tabIndex = 0; - if (d.activeElement === _this) { - _this.parentNode.focus(); - } - return _this.tabIndex = -1; - } else { - $.addClass(_this.parentNode, 'error'); - return $.one(_this, 'click', Metadata.load); - } - }; - })(this), { - Range: 'bytes=0-9999' - }); - }, - parse: function(data) { - var element, i, readInt, size, title; - readInt = function() { - var len, n; - n = data[i++]; - len = 0; - while (n < (0x80 >> len)) { - len++; - } - n ^= 0x80 >> len; - while (len-- && i < data.length) { - n = (n << 8) ^ data[i++]; - } - return n; - }; - i = 0; - while (i < data.length) { - element = readInt(); - size = readInt(); - if (element === 0x3BA9) { - title = ''; - while (size-- && i < data.length) { - title += String.fromCharCode(data[i++]); - } - return decodeURIComponent(escape(title)); - } else if (element !== 0x8538067 && element !== 0x549A966) { - i += size; - } - } - return null; - } - }; - - return Metadata; - -}).call(this); - -RevealSpoilers = (function() { - var RevealSpoilers; - - RevealSpoilers = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Reveal Spoiler Thumbnails'])) { - return; - } - return Callbacks.Post.push({ - name: 'Reveal Spoiler Thumbnails', - cb: this.node - }); - }, - node: function() { - var file, i, len, ref, thumb; - if (this.isClone) { - return; - } - ref = this.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (!(file.thumb && file.isSpoiler)) { - continue; - } - thumb = file.thumb; - thumb.removeAttribute('style'); - thumb.style.maxHeight = thumb.style.maxWidth = this.isReply ? '125px' : '250px'; - if (thumb.src) { - thumb.src = file.thumbURL; - } else { - thumb.dataset.src = file.thumbURL; - } - } - } - }; - - return RevealSpoilers; - -}).call(this); - -Sauce = (function() { - var Sauce, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Sauce = { - init: function() { - var j, len, link, linkData, links, ref, ref1; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Sauce'])) { - return; - } - $.addClass(doc, 'show-sauce'); - links = []; - ref1 = Conf['sauces'].split('\n'); - for (j = 0, len = ref1.length; j < len; j++) { - link = ref1[j]; - if (link[0] !== '#' && (linkData = this.parseLink(link))) { - links.push(linkData); - } - } - if (!links.length) { - return; - } - this.links = links; - this.link = $.el('a', { - target: '_blank', - className: 'sauce' - }); - return Callbacks.Post.push({ - name: 'Sauce', - cb: this.node - }); - }, - parseLink: function(link) { - var err, i, j, len, m, part, parts, ref, ref1, regexp; - if (!(link = link.trim())) { - return null; - } - parts = $.dict(); - ref = link.split(/;(?=(?:text|boards|types|regexp|sandbox):?)/); - for (i = j = 0, len = ref.length; j < len; i = ++j) { - part = ref[i]; - if (i === 0) { - parts['url'] = part; - } else { - m = part.match(/^(\w*):?(.*)$/); - parts[m[1]] = m[2]; - } - } - parts['text'] || (parts['text'] = ((ref1 = parts['url'].match(/(\w+)\.\w+\//)) != null ? ref1[1] : void 0) || '?'); - if ('boards' in parts) { - parts['boards'] = Filter.parseBoards(parts['boards']); - } - if ('regexp' in parts) { - try { - if ((regexp = parts['regexp'].match(/^\/(.*)\/(\w*)$/))) { - parts['regexp'] = RegExp(regexp[1], regexp[2]); - } else { - parts['regexp'] = RegExp(parts['regexp']); - } - } catch (error) { - err = error; - new Notice('warning', [$.tn("Invalid regexp for Sauce link:"), $.el('br'), $.tn(link), $.el('br'), $.tn(err.message)], 60); - return null; - } - } - return parts; - }, - createSauceLink: function(link, post, file) { - var a, base, ext, j, key, len, matches, missing, parts, ref; - ext = file.url.match(/[^.]*$/)[0]; - parts = $.dict(); - $.extend(parts, link); - if (!(!parts['boards'] || parts['boards'][post.siteID + "/" + post.boardID] || parts['boards'][post.siteID + "/*"])) { - return null; - } - if (!(!parts['types'] || indexOf.call(parts['types'].split(','), ext) >= 0)) { - return null; - } - if (!(!parts['regexp'] || (matches = file.name.match(parts['regexp'])))) { - return null; - } - missing = []; - ref = ['url', 'text']; - for (j = 0, len = ref.length; j < len; j++) { - key = ref[j]; - parts[key] = parts[key].replace(/%(T?URL|IMG|[sh]?MD5|board|name|%|semi|\$\d+)/g, function(orig, parameter) { - var type; - if (parameter[0] === '$') { - if (!matches) { - return orig; - } - type = matches[parameter.slice(1)] || ''; - } else { - type = Sauce.formatters[parameter](post, file, ext); - if (type == null) { - missing.push(parameter); - return ''; - } - } - if (key === 'url' && (parameter !== '%' && parameter !== 'semi')) { - if (/^javascript:/i.test(parts['url'])) { - type = JSON.stringify(type); - } - type = encodeURIComponent(type); - } - return type; - }); - } - if ((typeof (base = g.SITE).areMD5sDeferred === "function" ? base.areMD5sDeferred(post.board) : void 0) && missing.length && !missing.filter(function(x) { - return !/^.?MD5$/.test(x); - }).length) { - a = Sauce.link.cloneNode(false); - a.dataset.skip = '1'; - return a; - } - if (missing.length) { - return null; - } - a = Sauce.link.cloneNode(false); - a.href = parts['url']; - a.textContent = parts['text']; - if (/^javascript:/i.test(parts['url'])) { - a.removeAttribute('target'); - } - return a; - }, - node: function() { - var file, j, len, ref; - if (this.isClone) { - return; - } - ref = this.files; - for (j = 0, len = ref.length; j < len; j++) { - file = ref[j]; - Sauce.file(this, file); - } - }, - file: function(post, file) { - var j, len, link, node, nodes, observer, ref, skipped; - nodes = []; - skipped = []; - ref = Sauce.links; - for (j = 0, len = ref.length; j < len; j++) { - link = ref[j]; - if ((node = Sauce.createSauceLink(link, post, file))) { - nodes.push($.tn(' '), node); - if (node.dataset.skip) { - skipped.push([link, node]); - } - } - } - $.add(file.text, nodes); - if (skipped.length) { - observer = new MutationObserver(function() { - var k, len1, node2, ref1; - if (file.text.dataset.md5) { - for (k = 0, len1 = skipped.length; k < len1; k++) { - ref1 = skipped[k], link = ref1[0], node = ref1[1]; - if ((node2 = Sauce.createSauceLink(link, post, file))) { - $.replace(node, node2); - } - } - return observer.disconnect(); - } - }); - return observer.observe(file.text, { - attributes: true - }); - } - }, - formatters: { - TURL: function(post, file) { - return file.thumbURL; - }, - URL: function(post, file) { - return file.url; - }, - IMG: function(post, file, ext) { - if (ext === 'gif' || ext === 'jpg' || ext === 'jpeg' || ext === 'png') { - return file.url; - } else { - return file.thumbURL; - } - }, - MD5: function(post, file) { - return file.MD5; - }, - sMD5: function(post, file) { - var ref; - return (ref = file.MD5) != null ? ref.replace(/[+\/=]/g, function(c) { - return { - '+': '-', - '/': '_', - '=': '' - }[c]; - }) : void 0; - }, - hMD5: function(post, file) { - var c; - if (file.MD5) { - return ((function() { - var j, len, ref, results; - ref = atob(file.MD5); - results = []; - for (j = 0, len = ref.length; j < len; j++) { - c = ref[j]; - results.push(("0" + (c.charCodeAt(0).toString(16))).slice(-2)); - } - return results; - })()).join(''); - } - }, - board: function(post) { - return post.board.ID; - }, - name: function(post, file) { - return file.name; - }, - '%': function() { - return '%'; - }, - semi: function() { - return ';'; - } - } - }; - - return Sauce; - -}).call(this); - -Volume = (function() { - var Volume; - - Volume = { - init: function() { - var base, ref, unmuteEntry, volumeEntry; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && (Conf['Image Expansion'] || Conf['Image Hover'] || Conf['Image Hover in Catalog'] || Conf['Gallery']))) { - return; - } - $.sync('Allow Sound', function(x) { - var ref1; - Conf['Allow Sound'] = x; - return (ref1 = Volume.inputs) != null ? ref1.unmute.checked = x : void 0; - }); - $.sync('Default Volume', function(x) { - var ref1; - Conf['Default Volume'] = x; - return (ref1 = Volume.inputs) != null ? ref1.volume.value = x : void 0; - }); - if (Conf['Mouse Wheel Volume']) { - Callbacks.Post.push({ - name: 'Mouse Wheel Volume', - cb: this.node - }); - } - if (typeof (base = g.SITE).noAudio === "function" ? base.noAudio(g.BOARD) : void 0) { - return; - } - if (Conf['Mouse Wheel Volume']) { - Callbacks.CatalogThread.push({ - name: 'Mouse Wheel Volume', - cb: this.catalogNode - }); - } - unmuteEntry = UI.checkbox('Allow Sound', 'Allow Sound'); - unmuteEntry.title = Config.main['Images and Videos']['Allow Sound'][1]; - volumeEntry = $.el('label', { - title: 'Default volume for videos.' - }); - $.extend(volumeEntry, {innerHTML: " Volume"}); - this.inputs = { - unmute: unmuteEntry.firstElementChild, - volume: volumeEntry.firstElementChild - }; - $.on(this.inputs.unmute, 'change', $.cb.checked); - $.on(this.inputs.volume, 'change', $.cb.value); - Header.menu.addEntry({ - el: unmuteEntry, - order: 200 - }); - return Header.menu.addEntry({ - el: volumeEntry, - order: 201 - }); - }, - setup: function(video) { - video.muted = !Conf['Allow Sound']; - video.volume = Conf['Default Volume']; - return $.on(video, 'volumechange', Volume.change); - }, - change: function() { - var items, key, muted, ref, val, volume; - ref = this, muted = ref.muted, volume = ref.volume; - items = { - 'Allow Sound': !muted, - 'Default Volume': volume - }; - for (key in items) { - val = items[key]; - if (Conf[key] === val) { - delete items[key]; - } - } - $.set(items); - $.extend(Conf, items); - if (Volume.inputs) { - Volume.inputs.unmute.checked = !muted; - return Volume.inputs.volume.value = volume; - } - }, - node: function() { - var base, file, i, len, ref; - if (typeof (base = g.SITE).noAudio === "function" ? base.noAudio(this.board) : void 0) { - return; - } - ref = this.files; - for (i = 0, len = ref.length; i < len; i++) { - file = ref[i]; - if (!file.isVideo) { - continue; - } - if (file.thumb) { - $.on(file.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - } - $.on($('.file-info', file.text) || file.link, 'wheel', Volume.wheel.bind(file.thumbLink)); - } - }, - catalogNode: function() { - var file; - file = this.thread.OP.files[0]; - if (!(file != null ? file.isVideo : void 0)) { - return; - } - return $.on(this.nodes.thumb, 'wheel', Volume.wheel.bind(Header.hover)); - }, - wheel: function(e) { - var el, volume; - if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { - return; - } - if (!(el = $('video:not([data-md5])', this))) { - return; - } - if (el.muted || !$.hasAudio(el)) { - return; - } - volume = el.volume + 0.1; - if (e.deltaY < 0) { - volume *= 1.1; - } - if (e.deltaY > 0) { - volume /= 1.1; - } - el.volume = $.minmax(volume - 0.1, 0, 1); - return e.preventDefault(); - } - }; - - return Volume; - -}).call(this); - -Embedding = (function() { - var Embedding, - slice = [].slice; - - Embedding = { - init: function() { - var j, len, ref, ref1, type; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Linkify'] && (Conf['Embedding'] || Conf['Link Title'] || Conf['Cover Preview']))) { - return; - } - this.types = $.dict(); - ref1 = this.ordered_types; - for (j = 0, len = ref1.length; j < len; j++) { - type = ref1[j]; - this.types[type.key] = type; - } - if (Conf['Embedding'] && g.VIEW !== 'archive') { - this.dialog = UI.dialog('embedding', {innerHTML: "
      "}); - this.media = $('#media-embed', this.dialog); - $.one(d, '4chanXInitFinished', this.ready); - $.on(d, 'IndexRefreshInternal', function() { - return g.posts.forEach(function(post) { - var embed, k, l, len1, len2, ref2, ref3; - ref2 = [post].concat(slice.call(post.clones)); - for (k = 0, len1 = ref2.length; k < len1; k++) { - post = ref2[k]; - ref3 = post.nodes.embedlinks; - for (l = 0, len2 = ref3.length; l < len2; l++) { - embed = ref3[l]; - Embedding.cb.catalogRemove.call(embed); - } - } - }); - }); - } - if (Conf['Link Title']) { - return $.on(d, '4chanXInitFinished PostsInserted', function() { - var key, ref2, ref3, service; - ref2 = Embedding.types; - for (key in ref2) { - service = ref2[key]; - if ((ref3 = service.title) != null ? ref3.batchSize : void 0) { - Embedding.flushTitles(service.title); - } - } - }); - } - }, - events: function(post) { - var data, el, i, items; - if (g.VIEW === 'archive') { - return; - } - if (Conf['Embedding']) { - i = 0; - items = post.nodes.embedlinks = $$('.embedder', post.nodes.comment); - while (el = items[i++]) { - $.on(el, 'click', Embedding.cb.click); - if ($.hasClass(el, 'embedded')) { - Embedding.cb.toggle.call(el); - } - } - } - if (Conf['Cover Preview']) { - i = 0; - items = $$('.linkify', post.nodes.comment); - while (el = items[i++]) { - if ((data = Embedding.services(el))) { - Embedding.preview(data); - } - } - } - }, - process: function(link, post) { - var data; - if (!(Conf['Embedding'] || Conf['Link Title'] || Conf['Cover Preview'])) { - return; - } - if ($.x('ancestor::pre', link)) { - return; - } - if (data = Embedding.services(link)) { - data.post = post; - if (Conf['Embedding'] && g.VIEW !== 'archive') { - Embedding.embed(data); - } - if (Conf['Link Title']) { - Embedding.title(data); - } - if (Conf['Cover Preview'] && g.VIEW !== 'archive') { - return Embedding.preview(data); - } - } - }, - services: function(link) { - var href, j, len, match, ref, type; - href = link.href; - ref = Embedding.ordered_types; - for (j = 0, len = ref.length; j < len; j++) { - type = ref[j]; - if ((match = type.regExp.exec(href))) { - return { - key: type.key, - uid: match[1], - options: match[2], - link: link - }; - } - } - }, - embed: function(data) { - var embed, href, key, link, name, options, post, ref, uid, value; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - href = link.href; - $.addClass(link, key.toLowerCase()); - embed = $.el('a', { - className: 'embedder', - href: 'javascript:;' - }, {innerHTML: "(unembed)"}); - ref = { - key: key, - uid: uid, - options: options, - href: href - }; - for (name in ref) { - value = ref[name]; - embed.dataset[name] = value; - } - $.on(embed, 'click', Embedding.cb.click); - $.after(link, [$.tn(' '), embed]); - post.nodes.embedlinks.push(embed); - if (Conf['Auto-embed'] && !Conf['Floating Embeds'] && !post.isFetchedQuote) { - if ($.hasClass(doc, 'catalog-mode')) { - return $.addClass(embed, 'embed-removed'); - } else { - return Embedding.cb.toggle.call(embed); - } - } - }, - ready: function() { - if (!Main.isThisPageLegit()) { - return; - } - $.addClass(Embedding.dialog, 'empty'); - $.on($('.close', Embedding.dialog), 'click', Embedding.closeFloat); - $.on($('.move', Embedding.dialog), 'mousedown', Embedding.dragEmbed); - $.on($('.jump', Embedding.dialog), 'click', function() { - if (doc.contains(Embedding.lastEmbed)) { - return Header.scrollTo(Embedding.lastEmbed); - } - }); - return $.add(d.body, Embedding.dialog); - }, - closeFloat: function() { - delete Embedding.lastEmbed; - $.addClass(Embedding.dialog, 'empty'); - return $.replace(Embedding.media.firstChild, $.el('div')); - }, - dragEmbed: function() { - var style; - style = Embedding.media.style; - if (Embedding.dragEmbed.mouseup) { - $.off(d, 'mouseup', Embedding.dragEmbed); - Embedding.dragEmbed.mouseup = false; - style.pointerEvents = ''; - return; - } - $.on(d, 'mouseup', Embedding.dragEmbed); - Embedding.dragEmbed.mouseup = true; - return style.pointerEvents = 'none'; - }, - title: function(data) { - var key, link, options, post, service, uid; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - if (!(service = Embedding.types[key].title)) { - return; - } - $.addClass(link, key.toLowerCase()); - if (service.batchSize) { - (service.queue || (service.queue = [])).push(data); - if (service.queue.length >= service.batchSize) { - return Embedding.flushTitles(service); - } - } else { - return CrossOrigin.cache(service.api(uid), (function() { - return Embedding.cb.title(this, data); - })); - } - }, - flushTitles: function(service) { - var cb, data, queue; - queue = service.queue; - if (!(queue != null ? queue.length : void 0)) { - return; - } - service.queue = []; - cb = function() { - var data, j, len; - for (j = 0, len = queue.length; j < len; j++) { - data = queue[j]; - Embedding.cb.title(this, data); - } - }; - return CrossOrigin.cache(service.api((function() { - var j, len, results; - results = []; - for (j = 0, len = queue.length; j < len; j++) { - data = queue[j]; - results.push(data.uid); - } - return results; - })()), cb); - }, - preview: function(data) { - var key, link, service, uid; - key = data.key, uid = data.uid, link = data.link; - if (!(service = Embedding.types[key].preview)) { - return; - } - return $.on(link, 'mouseover', function(e) { - var el, height, src; - src = service.url(uid); - height = service.height; - el = $.el('img', { - src: src, - id: 'ihover' - }); - $.add(Header.hover, el); - return UI.hover({ - root: link, - el: el, - latestEvent: e, - endEvents: 'mouseout click', - height: height - }); - }); - }, - cb: { - click: function(e) { - var div; - e.preventDefault(); - if (!$.hasClass(this, 'embedded') && (Conf['Floating Embeds'] || $.hasClass(doc, 'catalog-mode'))) { - if (!(div = Embedding.media.firstChild)) { - return; - } - $.replace(div, Embedding.cb.embed(this)); - Embedding.lastEmbed = Get.postFromNode(this).nodes.root; - return $.rmClass(Embedding.dialog, 'empty'); - } else { - return Embedding.cb.toggle.call(this); - } - }, - toggle: function() { - if ($.hasClass(this, "embedded")) { - $.rm(this.nextElementSibling); - } else { - $.after(this, Embedding.cb.embed(this)); - } - return $.toggleClass(this, 'embedded'); - }, - embed: function(a) { - var container, el, type; - container = $.el('div', { - className: 'media-embed' - }); - $.add(container, el = (type = Embedding.types[a.dataset.key]).el(a)); - el.style.cssText = type.style != null ? type.style : 'border: none; width: 640px; height: 360px;'; - return container; - }, - catalogRemove: function() { - var isCatalog; - isCatalog = $.hasClass(doc, 'catalog-mode'); - if ((isCatalog && $.hasClass(this, 'embedded')) || (!isCatalog && $.hasClass(this, 'embed-removed'))) { - Embedding.cb.toggle.call(this); - return $.toggleClass(this, 'embed-removed'); - } - }, - title: function(req, data) { - var base1, j, k, key, len, len1, link, link2, options, post, post2, ref, ref1, service, status, text, uid; - key = data.key, uid = data.uid, options = data.options, link = data.link, post = data.post; - service = Embedding.types[key].title; - status = req.status; - if ((status === 200 || status === 304) && service.status) { - status = service.status(req.response)[0]; - } - if (!status) { - return; - } - text = "[" + key + "] " + ((function() { - switch (status) { - case 200: - case 304: - text = service.text(req.response, uid); - if (typeof text === 'string') { - return text; - } else { - return text = link.textContent; - } - break; - case 404: - return "Not Found"; - case 403: - case 401: - return "Forbidden or Private"; - default: - return status + "'d"; - } - })()); - link.dataset.original = link.textContent; - link.textContent = text; - ref = post.clones; - for (j = 0, len = ref.length; j < len; j++) { - post2 = ref[j]; - ref1 = $$('a.linkify', post2.nodes.comment); - for (k = 0, len1 = ref1.length; k < len1; k++) { - link2 = ref1[k]; - if (!(link2.href === link.href)) { - continue; - } - if ((base1 = link2.dataset).original == null) { - base1.original = link2.textContent; - } - link2.textContent = text; - } - } - } - }, - ordered_types: [ - { - key: 'audio', - regExp: /^[^?#]+\.(?:mp3|m4a|oga|wav|flac)(?:[?#]|$)/i, - style: '', - el: function(a) { - return $.el('audio', { - controls: true, - preload: 'auto', - src: a.dataset.href - }); - } - }, { - key: 'image', - regExp: /^[^?#]+\.(?:gif|png|jpg|jpeg|bmp|webp)(?::\w+)?(?:[?#]|$)/i, - style: '', - el: function(a) { - return $.el('div', {innerHTML: ""}); - } - }, { - key: 'video', - regExp: /^[^?#]+\.(?:og[gv]|webm|mp4)(?:[?#]|$)/i, - style: 'max-width: 80vw; max-height: 80vh;', - el: function(a) { - var el; - el = $.el('video', { - hidden: true, - controls: true, - preload: 'auto', - src: a.dataset.href, - loop: ImageHost.test(a.dataset.href.split('/')[2]) - }); - $.on(el, 'loadedmetadata', function() { - if (el.videoHeight === 0 && el.parentNode) { - return $.replace(el, Embedding.types.audio.el(a)); - } else { - return el.hidden = false; - } - }); - return el; - } - }, { - key: 'PeerTube', - regExp: /^(\w+:\/\/[^\/]+\/videos\/watch\/\w{8}-\w{4}-\w{4}-\w{4}-\w{12})(.*)/, - el: function(a) { - var el, options, start; - options = (start = a.dataset.options.match(/[?&](start=\w+)/)) ? "?" + start[1] : ''; - el = $.el('iframe', { - src: a.dataset.uid.replace('/videos/watch/', '/videos/embed/') + options - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'BitChute', - regExp: /^\w+:\/\/(?:www\.)?bitchute\.com\/video\/([\w\-]+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://www.bitchute.com/embed/" + a.dataset.uid + "/" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Clyp', - regExp: /^\w+:\/\/(?:www\.)?clyp\.it\/(\w{8})/, - style: 'border: 0; width: 640px; height: 160px;', - el: function(a) { - return $.el('iframe', { - src: "https://clyp.it/" + a.dataset.uid + "/widget" - }); - }, - title: { - api: function(uid) { - return "https://api.clyp.it/oembed?url=https://clyp.it/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'Dailymotion', - regExp: /^\w+:\/\/(?:(?:www\.)?dailymotion\.com\/(?:embed\/)?video|dai\.ly)\/([A-Za-z0-9]+)[^?]*(.*)/, - el: function(a) { - var el, options, start; - options = (start = a.dataset.options.match(/[?&](start=\d+)/)) ? "?" + start[1] : ''; - el = $.el('iframe', { - src: "//www.dailymotion.com/embed/video/" + a.dataset.uid + options - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://api.dailymotion.com/video/" + uid; - }, - text: function(_) { - return _.title; - } - }, - preview: { - url: function(uid) { - return "https://www.dailymotion.com/thumbnail/video/" + uid; - }, - height: 240 - } - }, { - key: 'Gfycat', - regExp: /^\w+:\/\/(?:www\.)?gfycat\.com\/(?:iframe\/)?(\w+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "//gfycat.com/ifr/" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Gist', - regExp: /^\w+:\/\/gist\.github\.com\/[\w\-]+\/(\w+)/, - style: '', - el: (function() { - var counter; - counter = 0; - return function(a) { - var el; - el = $.el('pre', { - hidden: true, - id: "gist-embed-" + (counter++) - }); - CrossOrigin.cache("https://api.github.com/gists/" + a.dataset.uid, function() { - el.textContent = Object.values(this.response.files)[0].content; - el.className = 'prettyprint'; - $.global(function() { - return typeof window.prettyPrint === "function" ? window.prettyPrint((function() {}), document.getElementById(document.currentScript.dataset.id).parentNode) : void 0; - }, { - id: el.id - }); - return el.hidden = false; - }); - return el; - }; - })(), - title: { - api: function(uid) { - return "https://api.github.com/gists/" + uid; - }, - text: function(arg) { - var file, files; - files = arg.files; - for (file in files) { - if (files.hasOwnProperty(file)) { - return file; - } - } - } - } - }, { - key: 'InstallGentoo', - regExp: /^\w+:\/\/paste\.installgentoo\.com\/view\/(?:raw\/|download\/|embed\/)?(\w+)/, - el: function(a) { - return $.el('iframe', { - src: "https://paste.installgentoo.com/view/embed/" + a.dataset.uid - }); - } - }, { - key: 'LiveLeak', - regExp: /^\w+:\/\/(?:\w+\.)?liveleak\.com\/.*\?.*[tif]=(\w+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://www.liveleak.com/e/" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Loopvid', - regExp: /^\w+:\/\/(?:www\.)?loopvid.appspot.com\/#?((?:pf|kd|lv|gd|gh|db|dx|nn|cp|wu|ig|ky|mf|m2|pc|1c|pi|ni|wl|ko|mm|ic|gc)\/[\w\-\/]+(?:,[\w\-\/]+)*|fc\/\w+\/\d+|https?:\/\/.+)/, - style: 'max-width: 80vw; max-height: 80vh;', - el: function(a) { - var _, base, el, host, j, k, l, len, len1, len2, name, names, ref, ref1, type, types, url, urls; - el = $.el('video', { - controls: true, - preload: 'auto', - loop: true - }); - if (/^http/.test(a.dataset.uid)) { - $.add(el, $.el('source', { - src: a.dataset.uid - })); - return el; - } - ref = a.dataset.uid.match(/(\w+)\/(.*)/), _ = ref[0], host = ref[1], names = ref[2]; - types = (function() { - switch (host) { - case 'gd': - case 'wu': - case 'fc': - return ['']; - case 'gc': - return ['giant', 'fat', 'zippy']; - default: - return ['.webm', '.mp4']; - } - })(); - ref1 = names.split(','); - for (j = 0, len = ref1.length; j < len; j++) { - name = ref1[j]; - for (k = 0, len1 = types.length; k < len1; k++) { - type = types[k]; - base = "" + name + type; - urls = (function() { - switch (host) { - case 'pf': - return ["https://kastden.org/_loopvid_media/pf/" + base, "https://web.archive.org/web/2/http://a.pomf.se/" + base]; - case 'kd': - return ["https://kastden.org/loopvid/" + base]; - case 'lv': - return ["https://lv.kastden.org/" + base]; - case 'gd': - return ["https://docs.google.com/uc?export=download&id=" + base]; - case 'gh': - return ["https://googledrive.com/host/" + base]; - case 'db': - return ["https://dl.dropboxusercontent.com/u/" + base]; - case 'dx': - return ["https://dl.dropboxusercontent.com/" + base]; - case 'nn': - return ["https://kastden.org/_loopvid_media/nn/" + base]; - case 'cp': - return ["https://copy.com/" + base]; - case 'wu': - return ["http://webmup.com/" + base + "/vid.webm"]; - case 'ig': - return ["https://i.imgur.com/" + base]; - case 'ky': - return ["https://kastden.org/_loopvid_media/ky/" + base]; - case 'mf': - return ["https://kastden.org/_loopvid_media/mf/" + base, "https://web.archive.org/web/2/https://d.maxfile.ro/" + base]; - case 'm2': - return ["https://kastden.org/_loopvid_media/m2/" + base]; - case 'pc': - return ["https://kastden.org/_loopvid_media/pc/" + base, "https://web.archive.org/web/2/http://a.pomf.cat/" + base]; - case '1c': - return ["http://b.1339.cf/" + base]; - case 'pi': - return ["https://kastden.org/_loopvid_media/pi/" + base, "https://web.archive.org/web/2/https://u.pomf.is/" + base]; - case 'ni': - return ["https://kastden.org/_loopvid_media/ni/" + base, "https://web.archive.org/web/2/https://u.nya.is/" + base]; - case 'wl': - return ["http://webm.land/media/" + base]; - case 'ko': - return ["https://kordy.kastden.org/loopvid/" + base]; - case 'mm': - return ["https://kastden.org/_loopvid_media/mm/" + base, "https://web.archive.org/web/2/https://my.mixtape.moe/" + base]; - case 'ic': - return ["https://media.8ch.net/file_store/" + base]; - case 'fc': - return ["//" + (ImageHost.host()) + "/" + base + ".webm"]; - case 'gc': - return ["https://" + type + ".gfycat.com/" + name + ".webm"]; - } - })(); - for (l = 0, len2 = urls.length; l < len2; l++) { - url = urls[l]; - $.add(el, $.el('source', { - src: url - })); - } - } - } - return el; - } - }, { - key: 'Openings.moe', - regExp: /^\w+:\/\/openings.moe\/\?video=([^.&=]+)/, - style: 'width: 1280px; height: 720px; max-width: 80vw; max-height: 80vh;', - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://openings.moe/?video=" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Pastebin', - regExp: /^\w+:\/\/(?:\w+\.)?pastebin\.com\/(?!u\/)(?:[\w.]+(?:\/|\?i\=))?(\w+)/, - el: function(a) { - var div; - return div = $.el('iframe', { - src: "//pastebin.com/embed_iframe.php?i=" + a.dataset.uid - }); - } - }, { - key: 'SoundCloud', - regExp: /^\w+:\/\/(?:www\.)?(?:soundcloud\.com\/|snd\.sc\/)([\w\-\/]+)/, - style: 'border: 0; width: 500px; height: 400px;', - el: function(a) { - return $.el('iframe', { - src: "https://w.soundcloud.com/player/?visual=true&show_comments=false&url=https%3A%2F%2Fsoundcloud.com%2F" + (encodeURIComponent(a.dataset.uid)) - }); - }, - title: { - api: function(uid) { - return location.protocol + "//soundcloud.com/oembed?format=json&url=https%3A%2F%2Fsoundcloud.com%2F" + (encodeURIComponent(uid)); - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'StrawPoll', - regExp: /^\w+:\/\/(?:www\.)?strawpoll\.me\/(?:embed_\d+\/)?(\d+(?:\/r)?)/, - style: 'border: 0; width: 600px; height: 406px;', - el: function(a) { - return $.el('iframe', { - src: "https://www.strawpoll.me/embed_1/" + a.dataset.uid - }); - } - }, { - key: 'Streamable', - regExp: /^\w+:\/\/(?:www\.)?streamable\.com\/(\w+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://streamable.com/o/" + a.dataset.uid - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://api.streamable.com/oembed?url=https://streamable.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'TwitchTV', - regExp: /^\w+:\/\/(?:www\.|secure\.|clips\.|m\.)?twitch\.tv\/(\w[^#\&\?]*)/, - el: function(a) { - var el, m, time, url; - m = a.dataset.href.match(/^\w+:\/\/(?:(clips\.)|\w+\.)?twitch\.tv\/(?:\w+\/)?(clip\/)?(\w[^#\&\?]*)/); - if (m[1] || m[2]) { - url = "//clips.twitch.tv/embed?clip=" + m[3] + "&parent=" + location.hostname; - } else { - m = a.dataset.uid.match(/(\w+)(?:\/(?:v\/)?(\d+))?/); - url = "//player.twitch.tv/?" + (m[2] ? "video=v" + m[2] : "channel=" + m[1]) + "&autoplay=false&parent=" + location.hostname; - if ((time = a.dataset.href.match(/\bt=(\w+)/))) { - url += "&time=" + time[1]; - } - } - el = $.el('iframe', { - src: url - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Twitter', - regExp: /^\w+:\/\/(?:www\.|mobile\.)?twitter\.com\/(\w+\/status\/\d+)/, - style: 'border: none; width: 550px; height: 250px; overflow: hidden; resize: both;', - el: function(a) { - var cont, el, onMessage; - el = $.el('iframe'); - $.on(el, 'load', function() { - return this.contentWindow.postMessage({ - element: 't', - query: 'height' - }, 'https://twitframe.com'); - }); - onMessage = function(e) { - if (e.source === el.contentWindow && e.origin === 'https://twitframe.com') { - $.off(window, 'message', onMessage); - return (cont || el).style.height = (+$.minmax(e.data.height, 250, 0.8 * doc.clientHeight)) + "px"; - } - }; - $.on(window, 'message', onMessage); - el.src = "https://twitframe.com/show?url=https://twitter.com/" + a.dataset.uid; - if ($.engine === 'gecko') { - el.style.cssText = 'border: none; width: 100%; height: 100%;'; - cont = $.el('div'); - $.add(cont, el); - return cont; - } else { - return el; - } - } - }, { - key: 'VidLii', - regExp: /^\w+:\/\/(?:www\.)?vidlii\.com\/watch\?v=(\w{11})/, - style: 'border: none; width: 640px; height: 392px;', - el: function(a) { - var el; - el = $.el('iframe', { - src: "https://www.vidlii.com/embed?v=" + a.dataset.uid + "&a=0" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - } - }, { - key: 'Vimeo', - regExp: /^\w+:\/\/(?:www\.)?vimeo\.com\/(\d+)/, - el: function(a) { - var el; - el = $.el('iframe', { - src: "//player.vimeo.com/video/" + a.dataset.uid + "?wmode=opaque" - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://vimeo.com/api/oembed.json?url=https://vimeo.com/" + uid; - }, - text: function(_) { - return _.title; - } - } - }, { - key: 'Vine', - regExp: /^\w+:\/\/(?:www\.)?vine\.co\/v\/(\w+)/, - style: 'border: none; width: 500px; height: 500px;', - el: function(a) { - return $.el('iframe', { - src: "https://vine.co/v/" + a.dataset.uid + "/card" - }); - } - }, { - key: 'Vocaroo', - regExp: /^\w+:\/\/(?:(?:www\.|old\.)?vocaroo\.com|voca\.ro)\/((?:i\/)?\w+)/, - style: '', - el: function(a) { - var el; - el = $.el('iframe'); - el.width = 300; - el.height = 60; - el.setAttribute('frameborder', 0); - el.src = "https://vocaroo.com/embed/" + (a.dataset.uid.replace(/^i\//, '')) + "?autoplay=0"; - return el; - } - }, { - key: 'YouTube', - regExp: /^\w+:\/\/(?:youtu.be\/|[\w.]*youtube[\w.]*\/.*(?:v=|\bembed\/|\bv\/))([\w\-]{11})(.*)/, - el: function(a) { - var el, start; - start = a.dataset.options.match(/\b(?:star)?t\=(\w+)/); - if (start) { - start = start[1]; - } - if (start && !/^\d+$/.test(start)) { - start += ' 0h0m0s'; - start = 3600 * start.match(/(\d+)h/)[1] + 60 * start.match(/(\d+)m/)[1] + 1 * start.match(/(\d+)s/)[1]; - } - el = $.el('iframe', { - src: "//www.youtube.com/embed/" + a.dataset.uid + "?rel=0&wmode=opaque" + (start ? '&start=' + start : '') - }); - el.setAttribute("allowfullscreen", "true"); - return el; - }, - title: { - api: function(uid) { - return "https://www.youtube.com/oembed?url=https%3A//www.youtube.com/watch%3Fv%3D" + uid + "&format=json"; - }, - text: function(_) { - return _.title; - }, - status: function(_) { - var m; - if (_.error) { - m = _.error.match(/^(\d*)\s*(.*)/); - return [+m[1], m[2]]; - } else { - return [200, 'OK']; - } - } - }, - preview: { - url: function(uid) { - return "https://img.youtube.com/vi/" + uid + "/0.jpg"; - }, - height: 360 - } - } - ] - }; - - return Embedding; - -}).call(this); - -Linkify = (function() { - var Linkify; - - Linkify = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') || !Conf['Linkify']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - Callbacks.Post.push({ - name: 'Linkify', - cb: this.node - }); - return Embedding.init(); - }, - node: function() { - var base, j, k, len, len1, link, links, ref; - if (this.isClone) { - return Embedding.events(this); - } - if (!Linkify.regString.test(this.info.comment)) { - return; - } - ref = $$('a', this.nodes.comment); - for (j = 0, len = ref.length; j < len; j++) { - link = ref[j]; - if (!(typeof (base = g.SITE).isLinkified === "function" ? base.isLinkified(link) : void 0)) { - continue; - } - $.addClass(link, 'linkify'); - if (ImageHost.useFaster) { - ImageHost.fixLinks([link]); - } - Embedding.process(link, this); - } - links = Linkify.process(this.nodes.comment); - if (ImageHost.useFaster) { - ImageHost.fixLinks(links); - } - for (k = 0, len1 = links.length; k < len1; k++) { - link = links[k]; - Embedding.process(link, this); - } - }, - process: function(node) { - var data, end, endNode, i, index, length, links, part1, part2, ref, ref1, result, saved, snapshot, space, test, word; - test = /[^\s"]+/g; - space = /[\s"]/; - snapshot = $.X('.//br|.//text()', node); - i = 0; - links = []; - while (node = snapshot.snapshotItem(i++)) { - data = node.data; - if (!data || node.parentElement.nodeName === "A") { - continue; - } - while (result = test.exec(data)) { - index = result.index; - endNode = node; - word = result[0]; - if ((length = index + word.length) === data.length) { - test.lastIndex = 0; - while ((saved = snapshot.snapshotItem(i++))) { - if (saved.nodeName === 'BR' || (saved.parentElement.nodeName === 'P' && !saved.previousSibling)) { - if ((part1 = word.match(/(https?:\/\/)?([a-z\d-]+\.)*[a-z\d-]+$/i)) && (part2 = (ref = snapshot.snapshotItem(i)) != null ? (ref1 = ref.data) != null ? ref1.match(/^(\.[a-z\d-]+)*\//i) : void 0 : void 0) && (part1[0] + part2[0]).search(Linkify.regString) === 0) { - continue; - } else { - break; - } - } - if (saved.parentElement.nodeName === "A" && !Linkify.regString.test(word)) { - break; - } - endNode = saved; - data = saved.data; - if (end = space.exec(data)) { - word += data.slice(0, end.index); - test.lastIndex = length = end.index; - i--; - break; - } else { - length = data.length; - word += data; - } - } - } - if (Linkify.regString.test(word)) { - links.push(Linkify.makeRange(node, endNode, index, length)); - } - if (!(test.lastIndex && node === endNode)) { - break; - } - } - } - i = links.length; - while (i--) { - links[i] = Linkify.makeLink(links[i]); - } - return links; - }, - regString: /((https?|mailto|git|magnet|ftp|irc):([a-z\d%\/?])|([-a-z\d]+[.])+(aero|asia|biz|cat|com|coop|dance|info|int|jobs|mobi|moe|museum|name|net|org|post|pro|tel|travel|xxx|xyz|edu|gov|mil|[a-z]{2})([:\/]|(?![^\s"]))|[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}|[-\w\d.@]+@[a-z\d.-]+\.[a-z\d])/i, - makeRange: function(startNode, endNode, startOffset, endOffset) { - var range; - range = document.createRange(); - range.setStart(startNode, startOffset); - range.setEnd(endNode, endOffset); - return range; - }, - makeLink: function(range) { - var a, encodedDomain, i, t, text; - text = range.toString(); - i = text.search(Linkify.regString); - if (i > 0) { - text = text.slice(i); - while (range.startOffset + i >= range.startContainer.data.length) { - i--; - } - if (i) { - range.setStart(range.startContainer, range.startOffset + i); - } - } - i = 0; - while (/[)\]}>.,]/.test(t = text.charAt(text.length - (1 + i)))) { - if (!(/[.,]/.test(t) || (text.match(/[()\[\]{}<>]/g)).length % 2)) { - break; - } - i++; - } - if (i) { - text = text.slice(0, -i); - while (range.endOffset - i < 0) { - i--; - } - if (i) { - range.setEnd(range.endContainer, range.endOffset - i); - } - } - if (!/((mailto|magnet):|.+:\/\/)/.test(text)) { - text = (/@/.test(text) ? 'mailto:' : 'http://') + text; - } - if (encodedDomain = text.match(/^(https?:\/\/[^\/]*%[0-9a-f]{2})(.*)$/i)) { - text = encodedDomain[1].replace(/%([0-9a-f]{2})/ig, function(x, y) { - if (y === '25') { - return x; - } else { - return String.fromCharCode(parseInt(y, 16)); - } - }) + encodedDomain[2]; - } - a = $.el('a', { - className: 'linkify', - rel: 'noreferrer noopener', - target: '_blank', - href: text - }); - $.add(a, range.extractContents()); - range.insertNode(a); - return a; - } - }; - - return Linkify; - -}).call(this); - -ArchiveLink = (function() { - var ArchiveLink; - - ArchiveLink = { - init: function() { - var div, entry, i, len, ref, ref1, type; - if (!(g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Archive Link'])) { - return; - } - div = $.el('div', { - textContent: 'Archive' - }); - entry = { - el: div, - order: 60, - open: function(arg) { - var ID, board, thread; - ID = arg.ID, thread = arg.thread, board = arg.board; - return !!Redirect.to('thread', { - postID: ID, - threadID: thread.ID, - boardID: board.ID - }); - }, - subEntries: [] - }; - ref1 = [['Post', 'post'], ['Name', 'name'], ['Tripcode', 'tripcode'], ['Capcode', 'capcode'], ['Subject', 'subject'], ['Flag', 'country'], ['Filename', 'filename'], ['Image MD5', 'MD5']]; - for (i = 0, len = ref1.length; i < len; i++) { - type = ref1[i]; - entry.subEntries.push(this.createSubEntry(type[0], type[1])); - } - return Menu.menu.addEntry(entry); - }, - createSubEntry: function(text, type) { - var el, open; - el = $.el('a', { - textContent: text, - target: '_blank' - }); - open = type === 'post' ? function(arg) { - var ID, board, thread; - ID = arg.ID, thread = arg.thread, board = arg.board; - el.href = Redirect.to('thread', { - postID: ID, - threadID: thread.ID, - boardID: board.ID - }); - return true; - } : function(post) { - var ref, typeParam, value; - typeParam = type === 'country' && post.info.flagCodeTroll ? 'troll_country' : type; - value = type === 'country' ? post.info.flagCode || ((ref = post.info.flagCodeTroll) != null ? ref.toLowerCase() : void 0) : Filter.values(type, post)[0]; - if (!value) { - return false; - } - el.href = Redirect.to('search', { - boardID: post.board.ID, - type: typeParam, - value: value, - isSearch: true - }); - return true; - }; - return { - el: el, - open: open - }; - } - }; - - return ArchiveLink; - -}).call(this); - -CopyTextLink = (function() { - var CopyTextLink; - - CopyTextLink = { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Copy Text Link'])) { - return; - } - a = $.el('a', { - className: 'copy-text-link', - href: 'javascript:;', - textContent: 'Copy Text' - }); - $.on(a, 'click', CopyTextLink.copy); - return Menu.menu.addEntry({ - el: a, - order: 12, - open: function(post) { - CopyTextLink.text = (post.origin || post).commentOrig(); - return true; - } - }); - }, - copy: function() { - var el; - el = $.el('textarea', { - className: 'copy-text-element', - value: CopyTextLink.text - }); - $.add(d.body, el); - el.select(); - try { - d.execCommand('copy'); - } catch (error) {} - return $.rm(el); - } - }; - - return CopyTextLink; - -}).call(this); - -DeleteLink = (function() { - var DeleteLink; - - DeleteLink = { - auto: [$.dict(), $.dict()], - init: function() { - var div, fileEl, fileEntry, postEl, postEntry, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Delete Link'])) { - return; - } - div = $.el('div', { - className: 'delete-link', - textContent: 'Delete' - }); - postEl = $.el('a', { - className: 'delete-post', - href: 'javascript:;' - }); - fileEl = $.el('a', { - className: 'delete-file', - href: 'javascript:;' - }); - this.nodes = { - menu: div.firstChild, - links: [postEl, fileEl] - }; - postEntry = { - el: postEl, - open: function() { - postEl.textContent = DeleteLink.linkText(false); - $.on(postEl, 'click', DeleteLink.toggle); - return true; - } - }; - fileEntry = { - el: fileEl, - open: function(arg) { - var file; - file = arg.file; - if (!file || file.isDead) { - return false; - } - fileEl.textContent = DeleteLink.linkText(true); - $.on(fileEl, 'click', DeleteLink.toggle); - return true; - } - }; - return Menu.menu.addEntry({ - el: div, - order: 40, - open: function(post) { - if (post.isDead) { - return false; - } - DeleteLink.post = post; - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - DeleteLink.cooldown.start(post); - return true; - }, - subEntries: [postEntry, fileEntry] - }); - }, - menuText: function() { - var seconds; - if (seconds = DeleteLink.cooldown.seconds[DeleteLink.post.fullID]) { - return "Delete (" + seconds + ")"; - } else { - return 'Delete'; - } - }, - linkText: function(fileOnly) { - var text; - text = fileOnly ? 'File' : 'Post'; - if (DeleteLink.auto[+fileOnly][DeleteLink.post.fullID]) { - text = "Deleting " + (text.toLowerCase()) + "..."; - } - return text; - }, - toggle: function() { - var auto, fileOnly, post; - post = DeleteLink.post; - fileOnly = $.hasClass(this, 'delete-file'); - auto = DeleteLink.auto[+fileOnly]; - if (auto[post.fullID]) { - delete auto[post.fullID]; - } else { - auto[post.fullID] = true; - } - this.textContent = DeleteLink.linkText(fileOnly); - if (!DeleteLink.cooldown.seconds[post.fullID]) { - return DeleteLink["delete"](post, fileOnly); - } - }, - "delete": function(post, fileOnly) { - var form, link; - link = DeleteLink.nodes.links[+fileOnly]; - delete DeleteLink.auto[+fileOnly][post.fullID]; - if (post.fullID === DeleteLink.post.fullID) { - $.off(link, 'click', DeleteLink.toggle); - } - form = { - mode: 'usrdel', - onlyimgdel: fileOnly, - pwd: QR.persona.getPassword() - }; - form[+post.ID] = 'delete'; - return $.ajax($.id('delform').action.replace("/" + g.BOARD + "/", "/" + post.board + "/"), { - responseType: 'document', - withCredentials: true, - onloadend: function() { - return DeleteLink.load(link, post, fileOnly, this.response); - }, - form: $.formData(form) - }); - }, - load: function(link, post, fileOnly, resDoc) { - var el, msg; - if (!resDoc) { - new Notice('warning', 'Connection error, please retry.', 20); - if (post.fullID === DeleteLink.post.fullID) { - $.on(link, 'click', DeleteLink.toggle); - } - return; - } - link.textContent = DeleteLink.linkText(fileOnly); - if (resDoc.title === '4chan - Banned') { - el = $.el('span', {innerHTML: "You can't delete posts because you are banned."}); - return new Notice('warning', el, 20); - } else if (msg = resDoc.getElementById('errmsg')) { - new Notice('warning', msg.textContent, 20); - if (post.fullID === DeleteLink.post.fullID) { - $.on(link, 'click', DeleteLink.toggle); - } - if (QR.cooldown.data && Conf['Cooldown'] && /\bwait\b/i.test(msg.textContent)) { - DeleteLink.cooldown.start(post, 5); - DeleteLink.auto[+fileOnly][post.fullID] = true; - return DeleteLink.nodes.links[+fileOnly].textContent = DeleteLink.linkText(fileOnly); - } - } else { - if (!fileOnly) { - QR.cooldown["delete"](post); - } - if (resDoc.title === 'Updating index...') { - (post.origin || post).kill(fileOnly); - } - if (post.fullID === DeleteLink.post.fullID) { - return link.textContent = 'Deleted'; - } - } - }, - cooldown: { - seconds: $.dict(), - start: function(post, seconds) { - if (DeleteLink.cooldown.seconds[post.fullID] != null) { - return; - } - if (seconds == null) { - seconds = QR.cooldown.secondsDeletion(post); - } - if (seconds > 0) { - DeleteLink.cooldown.seconds[post.fullID] = seconds; - return DeleteLink.cooldown.count(post); - } - }, - count: function(post) { - var fileOnly, i, len, ref; - if (post.fullID === DeleteLink.post.fullID) { - DeleteLink.nodes.menu.textContent = DeleteLink.menuText(); - } - if (DeleteLink.cooldown.seconds[post.fullID] > 0 && Conf['Cooldown']) { - DeleteLink.cooldown.seconds[post.fullID]--; - setTimeout(DeleteLink.cooldown.count, 1000, post); - } else { - delete DeleteLink.cooldown.seconds[post.fullID]; - ref = [false, true]; - for (i = 0, len = ref.length; i < len; i++) { - fileOnly = ref[i]; - if (DeleteLink.auto[+fileOnly][post.fullID]) { - DeleteLink["delete"](post, fileOnly); - } - } - } - } - } - }; - - return DeleteLink; - -}).call(this); - -DownloadLink = (function() { - var DownloadLink; - - DownloadLink = { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Download Link'])) { - return; - } - a = $.el('a', { - className: 'download-link', - textContent: 'Download file' - }); - $.on(a, 'click', ImageCommon.download); - return Menu.menu.addEntry({ - el: a, - order: 100, - open: function(arg) { - var file; - file = arg.file; - if (!file) { - return false; - } - a.href = file.url; - a.download = file.name; - return true; - } - }); - } - }; - - return DownloadLink; - -}).call(this); - -Menu = (function() { - var Menu; - - Menu = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'])) { - return; - } - this.button = $.el('a', { - className: 'menu-button', - href: 'javascript:;' - }); - $.extend(this.button, {innerHTML: ""}); - this.menu = new UI.Menu('post'); - Callbacks.Post.push({ - name: 'Menu', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Menu', - cb: this.catalogNode - }); - }, - node: function() { - var button; - if (this.isClone) { - button = $('.menu-button', this.nodes.info); - $.rmClass(button, 'active'); - $.rm($('.dialog', this.nodes.info)); - Menu.makeButton(this, button); - return; - } - return $.add(this.nodes.info, Menu.makeButton(this)); - }, - catalogNode: function() { - return $.after(this.nodes.icons, Menu.makeButton(this.thread.OP)); - }, - makeButton: function(post, button) { - button || (button = Menu.button.cloneNode(true)); - $.on(button, 'click', function(e) { - return Menu.menu.toggle(e, this, post); - }); - return button; - } - }; - - return Menu; - -}).call(this); - -ReportLink = (function() { - var ReportLink; - - ReportLink = { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Report Link'])) { - return; - } - a = $.el('a', { - className: 'report-link', - href: 'javascript:;', - textContent: 'Report' - }); - $.on(a, 'click', ReportLink.report); - return Menu.menu.addEntry({ - el: a, - order: 10, - open: function(post) { - ReportLink.url = "//sys." + (location.hostname.split('.')[1]) + ".org/" + post.board + "/imgboard.php?mode=report&no=" + post; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - ReportLink.dims = 'width=350,height=275'; - } else { - ReportLink.dims = 'width=400,height=550'; - } - return true; - } - }); - }, - report: function() { - var dims, id, set, url; - url = ReportLink.url, dims = ReportLink.dims; - id = Date.now(); - set = "toolbar=0,scrollbars=1,location=0,status=1,menubar=0,resizable=1," + dims; - return window.open(url, id, set); - } - }; - - return ReportLink; - -}).call(this); - -AntiAutoplay = (function() { - var AntiAutoplay; - - AntiAutoplay = { - init: function() { - var audio, i, len, ref; - if (!Conf['Disable Autoplaying Sounds']) { - return; - } - $.addClass(doc, 'anti-autoplay'); - ref = $$('audio[autoplay]', doc); - for (i = 0, len = ref.length; i < len; i++) { - audio = ref[i]; - this.stop(audio); - } - window.addEventListener('loadstart', ((function(_this) { - return function(e) { - return _this.stop(e.target); - }; - })(this)), true); - Callbacks.Post.push({ - name: 'Disable Autoplaying Sounds', - cb: this.node - }); - return $.ready((function(_this) { - return function() { - return _this.process(d.body); - }; - })(this)); - }, - stop: function(audio) { - if (!audio.autoplay) { - return; - } - audio.pause(); - audio.autoplay = false; - if (audio.controls) { - return; - } - audio.controls = true; - return $.addClass(audio, 'controls-added'); - }, - node: function() { - return AntiAutoplay.process(this.nodes.comment); - }, - process: function(root) { - var i, iframe, j, len, len1, object, ref, ref1; - ref = $$('iframe[src*="youtube"][src*="autoplay=1"]', root); - for (i = 0, len = ref.length; i < len; i++) { - iframe = ref[i]; - AntiAutoplay.processVideo(iframe, 'src'); - } - ref1 = $$('object[data*="youtube"][data*="autoplay=1"]', root); - for (j = 0, len1 = ref1.length; j < len1; j++) { - object = ref1[j]; - AntiAutoplay.processVideo(object, 'data'); - } - }, - processVideo: function(el, attr) { - el[attr] = el[attr].replace(/\?autoplay=1&?/, '?').replace('&autoplay=1', ''); - if (window.getComputedStyle(el).display === 'none') { - el.style.display = 'block'; - } - return $.addClass(el, 'autoplay-removed'); - } - }; - - return AntiAutoplay; - -}).call(this); - -Banner = (function() { - var Banner, - slice = [].slice; - - Banner = { - init: function() { - if (Conf['Custom Board Titles']) { - this.db = new DataBoard('customTitles', null, true); - } - $.asap((function() { - return d.body; - }), function() { - return $.asap((function() { - return $('hr'); - }), Banner.ready); - }); - if (g.BOARD.ID !== 'f') { - return Main.ready(function() { - return $.queueTask(Banner.load); - }); - } - }, - ready: function() { - var banner, children; - banner = $(".boardBanner"); - children = banner.children; - if (g.VIEW === 'thread' && Conf['Remove Thread Excerpt']) { - Banner.setTitle(children[1].textContent); - } - children[0].title = "Click to change"; - $.on(children[0], 'click', Banner.cb.toggle); - if (Conf['Custom Board Titles']) { - Banner.custom(children[1]); - if (children[2]) { - return Banner.custom(children[2]); - } - } - }, - load: function() { - var bannerCnt, img; - bannerCnt = $.id('bannerCnt'); - if (!bannerCnt.firstChild) { - img = $.el('img', { - alt: '4chan', - src: '//s.4cdn.org/image/title/' + bannerCnt.dataset.src - }); - return $.add(bannerCnt, img); - } - }, - setTitle: function(title) { - if (Unread.title != null) { - Unread.title = title; - return Unread.update(); - } else { - return d.title = title; - } - }, - cb: { - toggle: function() { - var banner, i, ref; - if (!((ref = Banner.choices) != null ? ref.length : void 0)) { - Banner.choices = Conf['knownBanners'].split(',').slice(); - } - i = Math.floor(Banner.choices.length * Math.random()); - banner = Banner.choices.splice(i, 1); - return $('img', this.parentNode).src = "//s.4cdn.org/image/title/" + banner; - }, - click: function(e) { - var base, br, j, len, name, ref; - if (!(e.ctrlKey || e.metaKey)) { - return; - } - if ((base = Banner.original)[name = this.className] == null) { - base[name] = this.cloneNode(true); - } - this.contentEditable = true; - ref = $$('br', this); - for (j = 0, len = ref.length; j < len; j++) { - br = ref[j]; - $.replace(br, $.tn('\n')); - } - return this.focus(); - }, - keydown: function(e) { - e.stopPropagation(); - if (!e.shiftKey && e.keyCode === 13) { - return this.blur(); - } - }, - blur: function() { - var br, j, len, ref; - ref = $$('br', this); - for (j = 0, len = ref.length; j < len; j++) { - br = ref[j]; - $.replace(br, $.tn('\n')); - } - if (this.textContent = this.textContent.replace(/\n*$/, '')) { - this.contentEditable = false; - return Banner.db.set({ - boardID: g.BOARD.ID, - threadID: this.className, - val: { - title: this.textContent, - orig: Banner.original[this.className].textContent - } - }); - } else { - $.rmAll(this); - $.add(this, slice.call(Banner.original[this.className].cloneNode(true).childNodes)); - return Banner.db["delete"]({ - boardID: g.BOARD.ID, - threadID: this.className - }); - } - } - }, - original: $.dict(), - custom: function(child) { - var className, data, event, j, len, ref; - className = child.className; - child.title = "Ctrl/\u2318+click to edit board " + (className.slice(5).toLowerCase()); - child.spellcheck = false; - ref = ['click', 'keydown', 'blur']; - for (j = 0, len = ref.length; j < len; j++) { - event = ref[j]; - $.on(child, event, Banner.cb[event]); - } - if (data = Banner.db.get({ - boardID: g.BOARD.ID, - threadID: className - })) { - if (Conf['Persistent Custom Board Titles'] || data.orig === child.textContent) { - Banner.original[className] = child.cloneNode(true); - return child.textContent = data.title; - } else { - return Banner.db["delete"]({ - boardID: g.BOARD.ID, - threadID: className - }); - } - } - } - }; - - return Banner; - -}).call(this); - -CatalogLinks = (function() { - var CatalogLinks; - - CatalogLinks = { - init: function() { - var el, input, selector; - if (g.SITE.software === 'yotsuba' && (Conf['External Catalog'] || Conf['JSON Index']) && !(Conf['JSON Index'] && g.VIEW === 'index')) { - selector = (function() { - switch (g.VIEW) { - case 'thread': - case 'archive': - return '.navLinks.desktop > a'; - case 'catalog': - return '.navLinks > :first-child > a'; - case 'index': - return '#ctrl-top > a, .cataloglink > a'; - } - })(); - $.ready(function() { - var base, catalogLink, catalogURL, i, len, link, link2, ref; - ref = $$(selector); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - switch (link.pathname.replace(/\/+/g, '/')) { - case "/" + g.BOARD + "/": - if (Conf['JSON Index']) { - link.textContent = 'Index'; - } - link.href = CatalogLinks.index(); - break; - case "/" + g.BOARD + "/catalog": - link.href = CatalogLinks.catalog(); - } - if (g.VIEW === 'catalog' && (catalogURL = CatalogLinks.catalog()) !== (typeof (base = g.SITE.urls).catalog === "function" ? base.catalog(g.BOARD) : void 0)) { - catalogLink = link.parentNode.cloneNode(true); - link2 = catalogLink.firstElementChild; - link2.href = catalogURL; - link2.textContent = link2.hostname === location.hostname ? '4chan X Catalog' : 'External Catalog'; - $.after(link.parentNode, [$.tn(' '), catalogLink]); - } - } - }); - } - if (g.SITE.software === 'yotsuba' && Conf['JSON Index'] && Conf['Use 4chan X Catalog']) { - Callbacks.Post.push({ - name: 'Catalog Link Rewrite', - cb: this.node - }); - } - if ((this.enabled = Conf['Catalog Links'])) { - CatalogLinks.el = el = UI.checkbox('Header catalog links', 'Catalog Links'); - el.id = 'toggleCatalog'; - input = $('input', el); - $.on(input, 'change', this.toggle); - $.sync('Header catalog links', CatalogLinks.set); - return Header.menu.addEntry({ - el: el, - order: 95 - }); - } - }, - node: function() { - var a, i, len, m, ref; - ref = $$('a', this.nodes.comment); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - if (m = a.href.match(/^https?:\/\/(boards\.4chan(?:nel)?\.org\/[^\/]+)\/catalog(#s=.*)?/)) { - a.href = "//" + m[1] + "/" + (m[2] || '#catalog'); - } - } - }, - toggle: function() { - $.event('CloseMenu'); - $.set('Header catalog links', this.checked); - return CatalogLinks.set(this.checked); - }, - set: function(useCatalog) { - Conf['Header catalog links'] = useCatalog; - CatalogLinks.setLinks(Header.boardList); - CatalogLinks.setLinks(Header.bottomBoardList); - CatalogLinks.el.title = "Turn catalog links " + (useCatalog ? 'off' : 'on') + "."; - return $('input', CatalogLinks.el).checked = useCatalog; - }, - setLinks: function(list) { - var VIEW, a, board, boardID, i, len, ref, ref1, ref2, ref3, siteID, tail, url; - if (!(((ref = CatalogLinks.enabled) != null ? ref : Conf['Catalog Links']) && list)) { - return; - } - tail = /(?:index)?(?:\.\w+)?$/; - ref1 = $$('a:not([data-only])', list); - for (i = 0, len = ref1.length; i < len; i++) { - a = ref1[i]; - ref2 = a.dataset, siteID = ref2.siteID, boardID = ref2.boardID; - if (!(siteID && boardID)) { - ref3 = Site.parseURL(a), siteID = ref3.siteID, boardID = ref3.boardID, VIEW = ref3.VIEW; - if (!(siteID && boardID && (VIEW === 'index' || VIEW === 'catalog') && (a.dataset.indexOptions || a.href.replace(tail, '') === (Get.url(VIEW, { - siteID: siteID, - boardID: boardID - }) || '').replace(tail, '')))) { - continue; - } - $.extend(a.dataset, { - siteID: siteID, - boardID: boardID - }); - } - board = { - siteID: siteID, - boardID: boardID - }; - url = Conf['Header catalog links'] ? CatalogLinks.catalog(board) : Get.url('index', board); - if (url) { - a.href = url; - if (a.dataset.indexOptions && url.split('#')[0] === Get.url('index', board)) { - a.href += (a.hash ? '/' : '#') + a.dataset.indexOptions; - } - } - } - }, - externalParse: function() { - var board, boards, excludes, i, len, line, ref, ref1, ref2, url; - CatalogLinks.externalList = $.dict(); - ref = Conf['externalCatalogURLs'].split('\n'); - for (i = 0, len = ref.length; i < len; i++) { - line = ref[i]; - if (line[0] === '#') { - continue; - } - url = line.split(';')[0]; - boards = Filter.parseBoards(((ref1 = line.match(/;boards:([^;]+)/)) != null ? ref1[1] : void 0) || '*'); - excludes = Filter.parseBoards((ref2 = line.match(/;exclude:([^;]+)/)) != null ? ref2[1] : void 0) || $.dict(); - for (board in boards) { - if (!(excludes[board] || excludes[board.split('/')[0] + '/*'])) { - CatalogLinks.externalList[board] = url; - } - } - } - }, - external: function(arg) { - var boardID, external, siteID; - siteID = arg.siteID, boardID = arg.boardID; - if (!CatalogLinks.externalList) { - CatalogLinks.externalParse(); - } - external = CatalogLinks.externalList[siteID + "/" + boardID] || CatalogLinks.externalList[siteID + "/*"]; - if (external) { - return external.replace(/%board/g, boardID); - } else { - return void 0; - } - }, - jsonIndex: function(board, hash) { - if (g.SITE.ID === board.siteID && g.BOARD.ID === board.boardID && g.VIEW === 'index') { - return hash; - } else { - return Get.url('index', board) + hash; - } - }, - catalog: function(board) { - var external, nativeCatalog; - if (board == null) { - board = g.BOARD; - } - if (Conf['External Catalog'] && (external = CatalogLinks.external(board))) { - return external; - } else if (Index.enabledOn(board) && Conf['Use 4chan X Catalog']) { - return CatalogLinks.jsonIndex(board, '#catalog'); - } else if ((nativeCatalog = Get.url('catalog', board))) { - return nativeCatalog; - } else { - return CatalogLinks.external(board); - } - }, - index: function(board) { - if (board == null) { - board = g.BOARD; - } - if (Index.enabledOn(board)) { - return CatalogLinks.jsonIndex(board, '#index'); - } else { - return Get.url('index', board); - } - } - }; - - return CatalogLinks; - -}).call(this); - -CustomCSS = (function() { - var CustomCSS; - - CustomCSS = { - init: function() { - if (!Conf['Custom CSS']) { - return; - } - return this.addStyle(); - }, - addStyle: function() { - return this.style = $.addStyle(CSS.sub(Conf['usercss']), 'custom-css', '#fourchanx-css'); - }, - rmStyle: function() { - if (this.style) { - $.rm(this.style); - return delete this.style; - } - }, - update: function() { - if (!this.style) { - return this.addStyle(); - } - return this.style.textContent = CSS.sub(Conf['usercss']); - } - }; - - return CustomCSS; - -}).call(this); - -ExpandComment = (function() { - var ExpandComment; - - ExpandComment = { - init: function() { - if (g.VIEW !== 'index' || !Conf['Comment Expansion'] || Conf['JSON Index']) { - return; - } - return Callbacks.Post.push({ - name: 'Comment Expansion', - cb: this.node - }); - }, - node: function() { - var a; - if (a = $('.abbr > a:not([onclick])', this.nodes.comment)) { - return $.on(a, 'click', ExpandComment.cb); - } - }, - callbacks: [], - cb: function(e) { - e.preventDefault(); - return ExpandComment.expand(Get.postFromNode(this)); - }, - expand: function(post) { - var a; - if (post.nodes.longComment && !post.nodes.longComment.parentNode) { - $.replace(post.nodes.shortComment, post.nodes.longComment); - post.nodes.comment = post.nodes.longComment; - return; - } - if (!(a = $('.abbr > a', post.nodes.comment))) { - return; - } - a.textContent = "Post No." + post + " Loading..."; - return $.cache(g.SITE.urls.threadJSON({ - boardID: post.boardID, - threadID: post.threadID - }), function() { - return ExpandComment.parse(this, a, post); - }); - }, - contract: function(post) { - var a; - if (!post.nodes.shortComment) { - return; - } - a = $('.abbr > a', post.nodes.shortComment); - a.textContent = 'here'; - $.replace(post.nodes.longComment, post.nodes.shortComment); - return post.nodes.comment = post.nodes.shortComment; - }, - parse: function(req, a, post) { - var callback, clone, comment, href, i, j, k, len, len1, len2, postObj, posts, quote, ref, ref1, spoilerRange, status; - status = req.status; - if (status !== 200 && status !== 304) { - a.textContent = status ? "Error " + req.statusText + " (" + status + ")" : 'Connection Error'; - return; - } - posts = req.response.posts; - if (spoilerRange = posts[0].custom_spoiler) { - g.SITE.Build.spoilerRange[g.BOARD] = spoilerRange; - } - for (i = 0, len = posts.length; i < len; i++) { - postObj = posts[i]; - if (postObj.no === post.ID) { - break; - } - } - if (postObj.no !== post.ID) { - a.textContent = "Post No." + post + " not found."; - return; - } - comment = post.nodes.comment; - clone = comment.cloneNode(false); - clone.innerHTML = postObj.com; - ref = $$('.quotelink', clone); - for (j = 0, len1 = ref.length; j < len1; j++) { - quote = ref[j]; - href = quote.getAttribute('href'); - if (href[0] === '/') { - continue; - } - if (href[0] === '#') { - quote.href = "" + (a.pathname.split(/\/+/).splice(0, 4).join('/')) + href; - } else { - quote.href = (a.pathname.split(/\/+/).splice(0, 3).join('/')) + "/" + href; - } - } - post.nodes.shortComment = comment; - $.replace(comment, clone); - post.nodes.comment = post.nodes.longComment = clone; - post.parseComment(); - post.parseQuotes(); - ref1 = ExpandComment.callbacks; - for (k = 0, len2 = ref1.length; k < len2; k++) { - callback = ref1[k]; - callback.call(post); - } - } - }; - - return ExpandComment; - -}).call(this); - -ExpandThread = (function() { - var ExpandThread, - slice = [].slice; - - ExpandThread = { - statuses: $.dict(), - init: function() { - if (!(g.VIEW === 'index' && Conf['Thread Expansion'])) { - return; - } - if (Conf['JSON Index']) { - return $.on(d, 'IndexRefreshInternal', this.onIndexRefresh); - } else { - return Callbacks.Thread.push({ - name: 'Expand Thread', - cb: function() { - return ExpandThread.setButton(this); - } - }); - } - }, - setButton: function(thread) { - var a, ref; - if (!(thread.nodes.root && (a = $('.summary', thread.nodes.root)))) { - return; - } - a.textContent = (ref = g.SITE.Build).summaryText.apply(ref, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - a.style.cursor = 'pointer'; - return $.on(a, 'click', ExpandThread.cbToggle); - }, - disconnect: function(refresh) { - var oldReq, ref, status, threadID; - if (g.VIEW === 'thread' || !Conf['Thread Expansion']) { - return; - } - ref = ExpandThread.statuses; - for (threadID in ref) { - status = ref[threadID]; - if ((oldReq = status.req)) { - delete status.req; - oldReq.abort(); - } - delete ExpandThread.statuses[threadID]; - } - if (!refresh) { - return $.off(d, 'IndexRefreshInternal', this.onIndexRefresh); - } - }, - onIndexRefresh: function() { - ExpandThread.disconnect(true); - return g.BOARD.threads.forEach(function(thread) { - return ExpandThread.setButton(thread); - }); - }, - cbToggle: function(e) { - if ($.modifiedClick(e)) { - return; - } - e.preventDefault(); - return ExpandThread.toggle(Get.threadFromNode(this)); - }, - cbToggleBottom: function(e) { - var bottom, thread; - if ($.modifiedClick(e)) { - return; - } - e.preventDefault(); - thread = Get.threadFromNode(this); - $.rm(this); - bottom = thread.nodes.root.getBoundingClientRect().bottom; - ExpandThread.toggle(thread); - return window.scrollBy(0, thread.nodes.root.getBoundingClientRect().bottom - bottom); - }, - toggle: function(thread) { - var a; - if (!(thread.nodes.root && (a = $('.summary', thread.nodes.root)))) { - return; - } - if (thread.ID in ExpandThread.statuses) { - return ExpandThread.contract(thread, a, thread.nodes.root); - } else { - return ExpandThread.expand(thread, a); - } - }, - expand: function(thread, a) { - var ref, status; - ExpandThread.statuses[thread] = status = {}; - a.textContent = (ref = g.SITE.Build).summaryText.apply(ref, ['...'].concat(slice.call(a.textContent.match(/\d+/g)))); - status.req = $.cache(g.SITE.urls.threadJSON({ - boardID: thread.board.ID, - threadID: thread.ID - }), function() { - if (this !== status.req) { - return; - } - delete status.req; - return ExpandThread.parse(this, thread, a); - }); - return status.numReplies = $$(g.SITE.selectors.replyOriginal, thread.nodes.root).length; - }, - contract: function(thread, a, threadRoot) { - var filesCount, i, inlined, len, oldReq, postsCount, ref, replies, reply, status; - status = ExpandThread.statuses[thread]; - delete ExpandThread.statuses[thread]; - if ((oldReq = status.req)) { - delete status.req; - oldReq.abort(); - if (a) { - a.textContent = (ref = g.SITE.Build).summaryText.apply(ref, ['+'].concat(slice.call(a.textContent.match(/\d+/g)))); - } - return; - } - replies = $$('.thread > .replyContainer', threadRoot); - if (status.numReplies) { - replies = replies.slice(0, -status.numReplies); - } - postsCount = 0; - filesCount = 0; - for (i = 0, len = replies.length; i < len; i++) { - reply = replies[i]; - if (Conf['Quote Inlining']) { - while (inlined = $('.inlined', reply)) { - inlined.click(); - } - } - postsCount++; - if ('file' in Get.postFromRoot(reply)) { - filesCount++; - } - $.rm(reply); - } - if (Index.enabled) { - $.event('PostsRemoved', null, a.parentNode); - } - a.textContent = g.SITE.Build.summaryText('+', postsCount, filesCount); - return $.rm($('.summary-bottom', threadRoot)); - }, - parse: function(req, thread, a) { - var a2, filesCount, i, len, post, postData, posts, postsCount, postsRoot, ref, ref1, root; - if ((ref = req.status) !== 200 && ref !== 304) { - a.textContent = req.status ? "Error " + req.statusText + " (" + req.status + ")" : 'Connection Error'; - return; - } - g.SITE.Build.spoilerRange[thread.board] = req.response.posts[0].custom_spoiler; - posts = []; - postsRoot = []; - filesCount = 0; - ref1 = req.response.posts; - for (i = 0, len = ref1.length; i < len; i++) { - postData = ref1[i]; - if (postData.no === thread.ID) { - continue; - } - if ((post = thread.posts.get(postData.no)) && !post.isFetchedQuote) { - if ('file' in post) { - filesCount++; - } - root = post.nodes.root; - postsRoot.push(root); - continue; - } - root = g.SITE.Build.postFromObject(postData, thread.board.ID); - post = new Post(root, thread, thread.board); - if ('file' in post) { - filesCount++; - } - posts.push(post); - postsRoot.push(root); - } - Main.callbackNodes('Post', posts); - $.after(a, postsRoot); - $.event('PostsInserted', null, a.parentNode); - postsCount = postsRoot.length; - a.textContent = g.SITE.Build.summaryText('-', postsCount, filesCount); - if (root) { - a2 = a.cloneNode(true); - a2.classList.add('summary-bottom'); - $.on(a2, 'click', ExpandThread.cbToggleBottom); - return $.after(root, a2); - } - } - }; - - return ExpandThread; - -}).call(this); - -FileInfo = (function() { - var FileInfo; - - FileInfo = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') || !Conf['File Info Formatting']) { - return; - } - return Callbacks.Post.push({ - name: 'File Info Formatting', - cb: this.node - }); - }, - node: function() { - var a, i, info, j, len, len1, oldInfo, ref, ref1; - if (!this.file) { - return; - } - if (this.isClone) { - ref = $$('.file-info .download-button', this.file.text); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - $.on(a, 'click', ImageCommon.download); - } - ref1 = $$('.file-info .quick-filter-md5', this.file.text); - for (j = 0, len1 = ref1.length; j < len1; j++) { - a = ref1[j]; - $.on(a, 'click', Filter.quickFilterMD5); - } - return; - } - oldInfo = $.el('span', { - className: 'fileText-original' - }); - $.prepend(this.file.link.parentNode, oldInfo); - $.add(oldInfo, [this.file.link.previousSibling, this.file.link, this.file.link.nextSibling]); - info = $.el('span', { - className: 'file-info' - }); - FileInfo.format(Conf['fileInfo'], this, info); - return $.prepend(this.file.text, info); - }, - format: function(formatString, post, outputNode) { - var a, i, j, len, len1, output, ref, ref1; - output = []; - formatString.replace(/%(.)|[^%]+/g, function(s, c) { - output.push($.hasOwn(FileInfo.formatters, c) ? FileInfo.formatters[c].call(post) : {innerHTML: E(s)}); - return ''; - }); - $.extend(outputNode, {innerHTML: E.cat(output)}); - ref = $$('.download-button', outputNode); - for (i = 0, len = ref.length; i < len; i++) { - a = ref[i]; - $.on(a, 'click', ImageCommon.download); - } - ref1 = $$('.quick-filter-md5', outputNode); - for (j = 0, len1 = ref1.length; j < len1; j++) { - a = ref1[j]; - $.on(a, 'click', Filter.quickFilterMD5); - } - }, - formatters: { - t: function() { - return {innerHTML: E(this.file.url.match(/[^/]*$/)[0])}; - }, - T: function() { - return {innerHTML: "" + (FileInfo.formatters.t.call(this)).innerHTML + ""}; - }, - l: function() { - return {innerHTML: "" + (FileInfo.formatters.n.call(this)).innerHTML + ""}; - }, - L: function() { - return {innerHTML: "" + (FileInfo.formatters.N.call(this)).innerHTML + ""}; - }, - n: function() { - var fullname, shortname; - fullname = this.file.name; - shortname = SW.yotsuba.Build.shortFilename(this.file.name, this.isReply); - if (fullname === shortname) { - return {innerHTML: E(fullname)}; - } else { - return {innerHTML: "" + E(shortname) + "" + E(fullname) + ""}; - } - }, - N: function() { - return {innerHTML: E(this.file.name)}; - }, - d: function() { - return {innerHTML: ""}; - }, - f: function() { - return {innerHTML: ""}; - }, - p: function() { - return {innerHTML: ((this.file.isSpoiler) ? "Spoiler, " : "")}; - }, - s: function() { - return {innerHTML: E(this.file.size)}; - }, - B: function() { - return {innerHTML: E(Math.round(this.file.sizeInBytes)) + " Bytes"}; - }, - K: function() { - return {innerHTML: E(Math.round(this.file.sizeInBytes/1024)) + " KB"}; - }, - M: function() { - return {innerHTML: E(Math.round(this.file.sizeInBytes/1048576*100)/100) + " MB"}; - }, - r: function() { - return {innerHTML: E(this.file.dimensions || "PDF")}; - }, - g: function() { - return {innerHTML: ((this.file.tag) ? ", " + E(this.file.tag) : "")}; - }, - '%': function() { - return {innerHTML: "%"}; - } - } - }; - - return FileInfo; - -}).call(this); - -Flash = (function() { - var Flash; - - Flash = { - init: function() { - if (g.BOARD.ID === 'f' && Conf['Enable Native Flash Embedding']) { - return $.ready(Flash.initReady); - } - }, - initReady: function() { - if ($.hasStorage) { - return $.global(function() { - if (JSON.parse(localStorage['4chan-settings'] || '{}').disableAll) { - return window.SWFEmbed.init(); - } - }); - } else { - if (g.VIEW === 'thread') { - $.global(function() { - return window.Main.tid = location.pathname.split(/\/+/)[3]; - }); - } - return $.global(function() { - return window.SWFEmbed.init(); - }); - } - } - }; - - return Flash; - -}).call(this); - -Fourchan = (function() { - var Fourchan; - - Fourchan = { - init: function() { - var ref; - if (!(g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive'))) { - return; - } - BoardConfig.ready(this.initBoard); - return Main.ready(this.initReady); - }, - initBoard: function() { - if (g.BOARD.config.code_tags) { - $.on(window, 'prettyprint:cb', function(e) { - var post, pre; - if (!(post = g.posts.get(e.detail.ID))) { - return; - } - if (!(pre = $$('.prettyprint', post.nodes.comment)[+e.detail.i])) { - return; - } - if (!$.hasClass(pre, 'prettyprinted')) { - pre.innerHTML = e.detail.html; - return $.addClass(pre, 'prettyprinted'); - } - }); - $.global(function() { - return window.addEventListener('prettyprint', function(e) { - return window.dispatchEvent(new CustomEvent('prettyprint:cb', { - detail: { - ID: e.detail.ID, - i: e.detail.i, - html: window.prettyPrintOne(e.detail.html) - } - })); - }, false); - }); - Callbacks.Post.push({ - name: 'Parse [code] tags', - cb: Fourchan.code - }); - g.posts.forEach(function(post) { - if (post.callbacksExecuted) { - return Callbacks.Post.execute(post, ['Parse [code] tags'], true); - } - }); - ExpandComment.callbacks.push(Fourchan.code); - } - if (g.BOARD.config.math_tags) { - $.global(function() { - return window.addEventListener('mathjax', function(e) { - if (window.MathJax) { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - } else { - if (!document.querySelector('script[src^="//cdn.mathjax.org/"]')) { - window.loadMathJax(); - window.loadMathJax = function() {}; - } - if (!e.target.classList.contains('postMessage')) { - return document.querySelector('script[src^="//cdn.mathjax.org/"]').addEventListener('load', function() { - return window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, e.target]); - }, false); - } - } - }, false); - }); - Callbacks.Post.push({ - name: 'Parse [math] tags', - cb: Fourchan.math - }); - g.posts.forEach(function(post) { - if (post.callbacksExecuted) { - return Callbacks.Post.execute(post, ['Parse [math] tags'], true); - } - }); - return ExpandComment.callbacks.push(Fourchan.math); - } - }, - initReady: function() { - return $.global(function() { - var j, len, node, ref; - window.clickable_ids = false; - ref = document.querySelectorAll('.posteruid, .capcode'); - for (j = 0, len = ref.length; j < len; j++) { - node = ref[j]; - node.removeEventListener('click', window.idClick, false); - } - }); - }, - code: function() { - if (this.isClone) { - return; - } - return $.ready((function(_this) { - return function() { - var i, j, len, pre, ref; - ref = $$('.prettyprint', _this.nodes.comment); - for (i = j = 0, len = ref.length; j < len; i = ++j) { - pre = ref[i]; - if (!$.hasClass(pre, 'prettyprinted')) { - $.event('prettyprint', { - ID: _this.fullID, - i: i, - html: pre.innerHTML - }, window); - } - } - }; - })(this)); - }, - math: function() { - var cb, j, len, wbr, wbrs; - if (!/\[(math|eqn)\]/.test(this.nodes.comment.textContent)) { - return; - } - if ((wbrs = $$('wbr', this.nodes.comment)).length) { - for (j = 0, len = wbrs.length; j < len; j++) { - wbr = wbrs[j]; - $.rm(wbr); - } - this.nodes.comment.normalize(); - } - cb = (function(_this) { - return function() { - if (!doc.contains(_this.nodes.comment)) { - return; - } - $.off(d, 'PostsInserted', cb); - return $.event('mathjax', null, _this.nodes.comment); - }; - })(this); - $.on(d, 'PostsInserted', cb); - return cb(); - } - }; - - return Fourchan; - -}).call(this); - -IDColor = (function() { - var IDColor; - - IDColor = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Color User IDs'])) { - return; - } - this.ids = $.dict(); - this.ids['Heaven'] = [0, 0, 0, '#fff']; - return Callbacks.Post.push({ - name: 'Color User IDs', - cb: this.node - }); - }, - node: function() { - var rgb, span, style, uid; - if (this.isClone || !((uid = this.info.uniqueID) && (span = this.nodes.uniqueID))) { - return; - } - rgb = IDColor.ids[uid] || IDColor.compute(uid); - style = span.style; - style.color = rgb[3]; - style.backgroundColor = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")"; - return $.addClass(span, 'painted'); - }, - compute: function(uid) { - var hash, rgb; - hash = g.SITE.uidColor ? g.SITE.uidColor(uid) : parseInt(uid, 16); - rgb = [(hash >> 16) & 0xFF, (hash >> 8) & 0xFF, hash & 0xFF]; - rgb.push($.luma(rgb) > 125 ? '#000' : '#fff'); - return this.ids[uid] = rgb; - } - }; - - return IDColor; - -}).call(this); - -IDHighlight = (function() { - var IDHighlight; - - IDHighlight = { - init: function() { - var ref; - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - return Callbacks.Post.push({ - name: 'Highlight by User ID', - cb: this.node - }); - }, - uniqueID: null, - node: function() { - if (this.nodes.uniqueIDRoot) { - $.on(this.nodes.uniqueIDRoot, 'click', IDHighlight.click(this)); - } - if (this.nodes.capcode) { - $.on(this.nodes.capcode, 'click', IDHighlight.click(this)); - } - if (!this.isClone) { - return IDHighlight.set(this); - } - }, - set: function(post) { - var match; - match = (post.info.uniqueID || post.info.capcode) === IDHighlight.uniqueID; - return $[match ? 'addClass' : 'rmClass'](post.nodes.post, 'highlight'); - }, - click: function(post) { - return function() { - var uniqueID; - uniqueID = post.info.uniqueID || post.info.capcode; - IDHighlight.uniqueID = IDHighlight.uniqueID === uniqueID ? null : uniqueID; - return g.posts.forEach(IDHighlight.set); - }; - } - }; - - return IDHighlight; - -}).call(this); - -IDPostCount = (function() { - var IDPostCount; - - IDPostCount = { - init: function() { - if (!(g.VIEW === 'thread' && Conf['Count Posts by ID'])) { - return; - } - Callbacks.Thread.push({ - name: 'Count Posts by ID', - cb: function() { - return IDPostCount.thread = this; - } - }); - return Callbacks.Post.push({ - name: 'Count Posts by ID', - cb: this.node - }); - }, - node: function() { - if (this.nodes.uniqueID && this.thread === IDPostCount.thread) { - return $.on(this.nodes.uniqueID, 'mouseover', IDPostCount.count); - } - }, - count: function() { - var n, uniqueID; - uniqueID = Get.postFromNode(this).info.uniqueID; - n = 0; - IDPostCount.thread.posts.forEach(function(post) { - if (post.info.uniqueID === uniqueID) { - return n++; - } - }); - return this.title = n + " post" + (n === 1 ? '' : 's') + " by this ID"; - } - }; - - return IDPostCount; - -}).call(this); - -Keybinds = (function() { - var Keybinds; - - Keybinds = { - init: function() { - var hotkey, init; - if (!Conf['Keybinds']) { - return; - } - for (hotkey in Config.hotkeys) { - $.sync(hotkey, Keybinds.sync); - } - init = function() { - var i, len, node, ref; - $.off(d, '4chanXInitFinished', init); - $.on(d, 'keydown', Keybinds.keydown); - ref = $$('[accesskey]'); - for (i = 0, len = ref.length; i < len; i++) { - node = ref[i]; - node.removeAttribute('accesskey'); - } - }; - return $.on(d, '4chanXInitFinished', init); - }, - sync: function(key, hotkey) { - return Conf[hotkey] = key; - }, - keydown: function(e) { - var base, base1, catalog, i, key, len, notification, notifications, post, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, searchInput, target, thread, threadRoot; - if (!(key = Keybinds.keyCode(e))) { - return; - } - target = e.target; - if ((ref = target.nodeName) === 'INPUT' || ref === 'TEXTAREA') { - if (!(/(Esc|Alt|Ctrl|Meta|Shift\+\w{2,})/.test(key) && !/^Alt\+(\d|Up|Down|Left|Right)$/.test(key))) { - return; - } - } - if ((ref1 = g.VIEW) === 'index' || ref1 === 'thread') { - threadRoot = Nav.getThread(); - thread = Get.threadFromRoot(threadRoot); - } - switch (key) { - case Conf['Toggle board list']: - if (!Conf['Custom Board Navigation']) { - return; - } - Header.toggleBoardList(); - break; - case Conf['Toggle header']: - Header.toggleBarVisibility(); - break; - case Conf['Open empty QR']: - if (!QR.postingIsEnabled) { - return; - } - Keybinds.qr(); - break; - case Conf['Open QR']: - if (!(QR.postingIsEnabled && threadRoot)) { - return; - } - Keybinds.qr(threadRoot); - break; - case Conf['Open settings']: - Settings.open(); - break; - case Conf['Close']: - if (Settings.dialog) { - Settings.close(); - } else if ((notifications = $$('.notification')).length) { - for (i = 0, len = notifications.length; i < len; i++) { - notification = notifications[i]; - $('.close', notification).click(); - } - } else if (QR.nodes && !(QR.nodes.el.hidden || window.getComputedStyle(QR.nodes.form).display === 'none')) { - if (Conf['Persistent QR']) { - QR.hide(); - } else { - QR.close(); - } - } else if (Embedding.lastEmbed) { - Embedding.closeFloat(); - } else { - return; - } - break; - case Conf['Spoiler tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('spoiler', target); - break; - case Conf['Code tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('code', target); - break; - case Conf['Eqn tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('eqn', target); - break; - case Conf['Math tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('math', target); - break; - case Conf['SJIS tags']: - if (target.nodeName !== 'TEXTAREA') { - return; - } - Keybinds.tags('sjis', target); - break; - case Conf['Toggle sage']: - if (!(QR.nodes && !QR.nodes.el.hidden)) { - return; - } - Keybinds.sage(); - break; - case Conf['Toggle Cooldown']: - if (!(QR.nodes && !QR.nodes.el.hidden && $.hasClass(QR.nodes.fileSubmit, 'custom-cooldown'))) { - return; - } - QR.toggleCustomCooldown(); - break; - case Conf['Post from URL']: - if (!QR.postingIsEnabled) { - return; - } - QR.handleUrl(''); - break; - case Conf['Add new post']: - if (!QR.postingIsEnabled) { - return; - } - QR.addPost(); - break; - case Conf['Submit QR']: - if (!(QR.nodes && !QR.nodes.el.hidden)) { - return; - } - if (!QR.status()) { - QR.submit(); - } - break; - case Conf['Update']: - switch (g.VIEW) { - case 'thread': - if (!ThreadUpdater.enabled) { - return; - } - ThreadUpdater.update(); - break; - case 'index': - if (!Index.enabled) { - return; - } - Index.update(); - break; - default: - return; - } - break; - case Conf['Watch']: - if (!(ThreadWatcher.enabled && thread)) { - return; - } - ThreadWatcher.toggle(thread); - break; - case Conf['Update thread watcher']: - if (!ThreadWatcher.enabled) { - return; - } - ThreadWatcher.buttonFetchAll(); - break; - case Conf['Toggle thread watcher']: - if (!ThreadWatcher.enabled) { - return; - } - ThreadWatcher.toggleWatcher(); - break; - case Conf['Toggle threading']: - if (!QuoteThreading.ready) { - return; - } - QuoteThreading.toggleThreading(); - break; - case Conf['Mark thread read']: - if (!(g.VIEW === 'index' && thread && UnreadIndex.enabled)) { - return; - } - UnreadIndex.markRead.call(threadRoot); - break; - case Conf['Expand image']: - if (!(ImageExpand.enabled && threadRoot)) { - return; - } - post = Get.postFromNode(Keybinds.post(threadRoot)); - if (post.file) { - ImageExpand.toggle(post); - } - break; - case Conf['Expand images']: - if (!ImageExpand.enabled) { - return; - } - ImageExpand.cb.toggleAll(); - break; - case Conf['Open Gallery']: - if (!Gallery.enabled) { - return; - } - Gallery.cb.toggle(); - break; - case Conf['fappeTyme']: - if (!((ref2 = FappeTyme.nodes) != null ? ref2.fappe : void 0)) { - return; - } - FappeTyme.toggle('fappe'); - break; - case Conf['werkTyme']: - if (!((ref3 = FappeTyme.nodes) != null ? ref3.werk : void 0)) { - return; - } - FappeTyme.toggle('werk'); - break; - case Conf['Front page']: - if (Index.enabled) { - Index.userPageNav(1); - } else { - location.href = "/" + g.BOARD + "/"; - } - break; - case Conf['Open front page']: - $.open(location.origin + "/" + g.BOARD + "/"); - break; - case Conf['Next page']: - if (!(g.VIEW === 'index' && !(typeof (base = g.SITE).isOnePage === "function" ? base.isOnePage(g.BOARD) : void 0))) { - return; - } - if (Index.enabled) { - if ((ref4 = Conf['Index Mode']) !== 'paged' && ref4 !== 'infinite') { - return; - } - $('.next button', Index.pagelist).click(); - } else { - if ((ref5 = $(g.SITE.selectors.nav.next)) != null) { - ref5.click(); - } - } - break; - case Conf['Previous page']: - if (!(g.VIEW === 'index' && !(typeof (base1 = g.SITE).isOnePage === "function" ? base1.isOnePage(g.BOARD) : void 0))) { - return; - } - if (Index.enabled) { - if ((ref6 = Conf['Index Mode']) !== 'paged' && ref6 !== 'infinite') { - return; - } - $('.prev button', Index.pagelist).click(); - } else { - if ((ref7 = $(g.SITE.selectors.nav.prev)) != null) { - ref7.click(); - } - } - break; - case Conf['Search form']: - if (g.VIEW !== 'index') { - return; - } - searchInput = Index.enabled ? Index.searchInput : g.SITE.selectors.searchBox ? $(g.SITE.selectors.searchBox) : void 0; - if (!searchInput) { - return; - } - Header.scrollToIfNeeded(searchInput); - searchInput.focus(); - break; - case Conf['Paged mode']: - if (!Index.enabledOn(g.BOARD)) { - return; - } - location.href = g.VIEW === 'index' ? '#paged' : "/" + g.BOARD + "/#paged"; - break; - case Conf['Infinite scrolling mode']: - if (!Index.enabledOn(g.BOARD)) { - return; - } - location.href = g.VIEW === 'index' ? '#infinite' : "/" + g.BOARD + "/#infinite"; - break; - case Conf['All pages mode']: - if (!Index.enabledOn(g.BOARD)) { - return; - } - location.href = g.VIEW === 'index' ? '#all-pages' : "/" + g.BOARD + "/#all-pages"; - break; - case Conf['Open catalog']: - if (!(catalog = CatalogLinks.catalog())) { - return; - } - location.href = catalog; - break; - case Conf['Cycle sort type']: - if (!Index.enabled) { - return; - } - Index.cycleSortType(); - break; - case Conf['Next thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Nav.scroll(+1); - break; - case Conf['Previous thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Nav.scroll(-1); - break; - case Conf['Expand thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - ExpandThread.toggle(thread); - Header.scrollTo(threadRoot); - break; - case Conf['Open thread']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Keybinds.open(thread); - break; - case Conf['Open thread tab']: - if (!(g.VIEW === 'index' && threadRoot)) { - return; - } - Keybinds.open(thread, true); - break; - case Conf['Next reply']: - if (!threadRoot) { - return; - } - Keybinds.hl(+1, threadRoot); - break; - case Conf['Previous reply']: - if (!threadRoot) { - return; - } - Keybinds.hl(-1, threadRoot); - break; - case Conf['Deselect reply']: - if (!threadRoot) { - return; - } - Keybinds.hl(0, threadRoot); - break; - case Conf['Hide']: - if (!(thread && ThreadHiding.db)) { - return; - } - Header.scrollTo(threadRoot); - ThreadHiding.toggle(thread); - break; - case Conf['Quick Filter MD5']: - if (!threadRoot) { - return; - } - post = Keybinds.post(threadRoot); - Keybinds.hl(+1, threadRoot); - Filter.quickFilterMD5.call(post, e); - break; - case Conf['Previous Post Quoting You']: - if (!(threadRoot && QuoteYou.db)) { - return; - } - QuoteYou.cb.seek('preceding'); - break; - case Conf['Next Post Quoting You']: - if (!(threadRoot && QuoteYou.db)) { - return; - } - QuoteYou.cb.seek('following'); - break; - default: - return; - } - e.preventDefault(); - return e.stopPropagation(); - }, - keyCode: function(e) { - var kc, key; - key = (function() { - switch (kc = e.keyCode) { - case 8: - return ''; - case 13: - return 'Enter'; - case 27: - return 'Esc'; - case 32: - return 'Space'; - case 37: - return 'Left'; - case 38: - return 'Up'; - case 39: - return 'Right'; - case 40: - return 'Down'; - case 188: - return 'Comma'; - case 190: - return 'Period'; - case 191: - return 'Slash'; - case 59: - case 186: - return 'Semicolon'; - default: - if ((48 <= kc && kc <= 57) || (65 <= kc && kc <= 90)) { - return String.fromCharCode(kc).toLowerCase(); - } else if ((96 <= kc && kc <= 105)) { - return String.fromCharCode(kc - 48).toLowerCase(); - } else { - return null; - } - } - })(); - if (key) { - if (e.altKey) { - key = 'Alt+' + key; - } - if (e.ctrlKey) { - key = 'Ctrl+' + key; - } - if (e.metaKey) { - key = 'Meta+' + key; - } - if (e.shiftKey) { - key = 'Shift+' + key; - } - } - return key; - }, - post: function(thread) { - var s; - s = g.SITE.selectors; - return $("" + s.postContainer + s.highlightable.reply + "." + g.SITE.classes.highlight, thread) || $("" + (g.SITE.isOPContainerThread ? s.thread : s.postContainer) + s.highlightable.op, thread); - }, - qr: function(thread) { - QR.open(); - if (thread != null) { - QR.quote.call(Keybinds.post(thread)); - } - return QR.nodes.com.focus(); - }, - tags: function(tag, ta) { - var range, selEnd, selStart, value; - BoardConfig.ready(function() { - var config, supported; - config = g.BOARD.config; - supported = (function() { - switch (tag) { - case 'spoiler': - return !!config.spoilers; - case 'code': - return !!config.code_tags; - case 'math': - case 'eqn': - return !!config.math_tags; - case 'sjis': - return !!config.sjis_tags; - } - })(); - if (!supported) { - return new Notice('warning', "[" + tag + "] tags are not supported on /" + g.BOARD + "/.", 20); - } - }); - 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('input', null, ta); - }, - sage: function() { - var isSage; - isSage = /sage/i.test(QR.nodes.email.value); - return QR.nodes.email.value = isSage ? "" : "sage"; - }, - open: function(thread, tab) { - var url; - if (g.VIEW !== 'index') { - return; - } - url = Get.url('thread', thread); - if (tab) { - return $.open(url); - } else { - return location.href = url; - } - }, - hl: function(delta, thread) { - var axis, height, highlight, i, len, next, postEl, replies, reply, replySelector, root; - replySelector = "" + g.SITE.selectors.postContainer + g.SITE.selectors.highlightable.reply; - highlight = g.SITE.classes.highlight; - postEl = $(replySelector + "." + highlight, thread); - if (!delta) { - if (postEl) { - $.rmClass(postEl, highlight); - } - return; - } - if (postEl) { - height = postEl.getBoundingClientRect().height; - if (Header.getTopOf(postEl) >= -height && Header.getBottomOf(postEl) >= -height) { - root = Get.postFromNode(postEl).nodes.root; - axis = delta === +1 ? 'following' : 'preceding'; - if (!(next = $.x(axis + "-sibling::" + g.SITE.xpath.replyContainer + "[not(@hidden) and not(child::div[@class='stub'])][1]", root))) { - return; - } - if (!next.matches(replySelector)) { - next = $(replySelector, next); - } - Header.scrollToIfNeeded(next, delta === +1); - $.addClass(next, highlight); - $.rmClass(postEl, highlight); - return; - } - $.rmClass(postEl, highlight); - } - replies = $$(replySelector, thread); - if (delta === -1) { - replies.reverse(); - } - for (i = 0, len = replies.length; i < len; i++) { - reply = replies[i]; - if (delta === +1 && Header.getTopOf(reply) > 0 || delta === -1 && Header.getBottomOf(reply) > 0) { - $.addClass(reply, highlight); - return; - } - } - } - }; - - return Keybinds; - -}).call(this); - -ModContact = (function() { - var ModContact; - - ModContact = { - init: function() { - var ref; - if (!(g.SITE.software === 'yotsuba' && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - return Callbacks.Post.push({ - name: 'Mod Contact Links', - cb: this.node - }); - }, - node: function() { - var links, moveNote, moved; - if (this.isClone || !$.hasOwn(ModContact.specific, this.info.capcode)) { - return; - } - links = $.el('span', { - className: 'contact-links brackets-wrap' - }); - $.extend(links, ModContact.template(this.info.capcode)); - $.after(this.nodes.capcode, links); - if ((moved = this.info.comment.match(/This thread was moved to >>>\/(\w+)\//)) && $.hasOwn(ModContact.moveNote, moved[1])) { - moveNote = $.el('div', { - className: 'move-note' - }); - $.extend(moveNote, ModContact.moveNote[moved[1]]); - return $.add(this.nodes.post, moveNote); - } - }, - template: function(capcode) { - return {innerHTML: "feedback" + (ModContact.specific[capcode]()).innerHTML}; - }, - specific: { - Mod: function() { - return {innerHTML: " IRC"}; - }, - Manager: function() { - return ModContact.specific.Mod(); - }, - Developer: function() { - return {innerHTML: " github"}; - }, - Admin: function() { - return {innerHTML: " twitter"}; - } - }, - moveNote: { - qa: {innerHTML: "Moving a thread to /qa/ does not imply mods will read it. If you wish to contact mods, use feedback (https://www.4chan.org/feedback) or IRC (https://www.4chan-x.net/4chan-irc.html)."} - } - }; - - return ModContact; - -}).call(this); - -Nav = (function() { - var Nav; - - Nav = { - init: function() { - var append, next, prev, span; - switch (g.VIEW) { - case 'index': - if (!Conf['Index Navigation']) { - return; - } - break; - case 'thread': - if (!Conf['Reply Navigation']) { - return; - } - break; - default: - return; - } - span = $.el('span', { - id: 'navlinks' - }); - prev = $.el('a', { - textContent: '▲', - href: 'javascript:;' - }); - next = $.el('a', { - textContent: '▼', - href: 'javascript:;' - }); - $.on(prev, 'click', this.prev); - $.on(next, 'click', this.next); - $.add(span, [prev, $.tn(' '), next]); - append = function() { - $.off(d, '4chanXInitFinished', append); - return $.add(d.body, span); - }; - return $.on(d, '4chanXInitFinished', append); - }, - prev: function() { - if (g.VIEW === 'thread') { - return window.scrollTo(0, 0); - } else { - return Nav.scroll(-1); - } - }, - next: function() { - if (g.VIEW === 'thread') { - return window.scrollTo(0, d.body.scrollHeight); - } else { - return Nav.scroll(+1); - } - }, - getThread: function() { - var i, len, ref, thread, threadRoot; - if (g.VIEW === 'thread') { - return g.threads.get(g.BOARD + "." + g.THREADID).nodes.root; - } - if ($.hasClass(doc, 'catalog-mode')) { - return; - } - ref = $$(g.SITE.selectors.thread); - for (i = 0, len = ref.length; i < len; i++) { - threadRoot = ref[i]; - thread = Get.threadFromRoot(threadRoot); - if (thread.isHidden && !thread.stub) { - continue; - } - if (Header.getTopOf(threadRoot) >= -threadRoot.getBoundingClientRect().height) { - return threadRoot; - } - } - }, - scroll: function(delta) { - var axis, extra, next, ref, thread, top; - if ((ref = d.activeElement) != null) { - ref.blur(); - } - thread = Nav.getThread(); - if (!thread) { - return; - } - axis = delta === +1 ? 'following' : 'preceding'; - if (next = $.x(axis + "-sibling::" + g.SITE.xpath.thread + "[not(@hidden)][1]", thread)) { - top = Header.getTopOf(thread); - if (delta === +1 && top < 5 || delta === -1 && top > -5) { - thread = next; - } - } - extra = Header.getTopOf(thread) + doc.clientHeight - d.body.getBoundingClientRect().bottom; - if (extra > 0) { - d.body.style.marginBottom = extra + "px"; - } - Header.scrollTo(thread); - if (extra > 0 && !Nav.haveExtra) { - Nav.haveExtra = true; - return $.on(d, 'scroll', Nav.removeExtra); - } - }, - removeExtra: function() { - var extra; - extra = doc.clientHeight - d.body.getBoundingClientRect().bottom; - if (extra > 0) { - return d.body.style.marginBottom = extra + "px"; - } else { - d.body.style.marginBottom = ''; - delete Nav.haveExtra; - return $.off(d, 'scroll', Nav.removeExtra); - } - } - }; - - return Nav; - -}).call(this); - -NormalizeURL = (function() { - var NormalizeURL; - - NormalizeURL = { - init: function() { - var pathname; - if (!Conf['Normalize URL']) { - return; - } - pathname = location.pathname.split(/\/+/); - if (g.SITE.software === 'yotsuba') { - switch (g.VIEW) { - case 'thread': - pathname[2] = 'thread'; - pathname = pathname.slice(0, 4); - break; - case 'index': - pathname = pathname.slice(0, 3); - } - } - pathname = pathname.join('/'); - if (location.pathname !== pathname) { - return history.replaceState(history.state, '', location.protocol + "//" + location.host + pathname + location.hash); - } - } - }; - - return NormalizeURL; - -}).call(this); - -PSA = (function() { - var PSA, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - PSA = { - init: function() { - var announcement, el; - if (g.SITE.software === 'yotsuba' && g.BOARD.ID === 'qa') { - announcement = { - innerHTML: "Stay in touch with your /qa/ friends!" - }; - el = $.el('div', { - className: 'fcx-announcement' - }, announcement); - $.onExists(doc, '.boardBanner', function(banner) { - return $.after(banner, el); - }); - } - if ('samachan.org' in Conf['siteProperties'] && indexOf.call(Conf['PSAseen'], 'samachan') < 0) { - el = $.el('span', { - innerHTML: "Looking for a new home?
      Some former Samachan users are regrouping on SushiChan.

      (a message from 4chan X)" - }); - return Main.ready(function() { - new Notice('info', el); - Conf['PSAseen'].push('samachan'); - return $.set('PSAseen', Conf['PSAseen']); - }); - } - } - }; - - return PSA; - -}).call(this); - -PSAHiding = (function() { - var PSAHiding, - slice = [].slice; - - PSAHiding = { - init: function() { - if (!(Conf['Announcement Hiding'] && g.SITE.selectors.psa)) { - return; - } - $.addClass(doc, 'hide-announcement'); - $.onExists(doc, g.SITE.selectors.psa, this.setup); - return $.ready(function() { - if (!$(g.SITE.selectors.psa)) { - return $.rmClass(doc, 'hide-announcement'); - } - }); - }, - setup: function(psa) { - var btn, entry, hr, ref, ref1, ref2; - PSAHiding.psa = psa; - PSAHiding.text = (ref = psa.dataset.utc) != null ? ref : psa.innerHTML; - if (g.SITE.selectors.psaTop && (hr = (ref1 = $(g.SITE.selectors.psaTop)) != null ? ref1.previousElementSibling : void 0) && hr.nodeName === 'HR') { - PSAHiding.hr = hr; - } - PSAHiding.content = $.el('div'); - entry = { - el: $.el('a', { - textContent: 'Show announcement', - className: 'show-announcement', - href: 'javascript:;' - }), - order: 50, - open: function() { - return psa.hidden; - } - }; - Header.menu.addEntry(entry); - $.on(entry.el, 'click', PSAHiding.toggle); - PSAHiding.btn = btn = $.el('a', { - title: 'Mark announcement as read and hide.', - className: 'hide-announcement-button fa fa-minus-square', - href: 'javascript:;' - }); - $.on(btn, 'click', PSAHiding.toggle); - if (((ref2 = psa.firstChild) != null ? ref2.tagName : void 0) === 'HR') { - $.after(psa.firstChild, btn); - } else { - $.prepend(psa, btn); - } - PSAHiding.sync(Conf['hiddenPSAList']); - $.rmClass(doc, 'hide-announcement'); - return $.sync('hiddenPSAList', PSAHiding.sync); - }, - toggle: function() { - var hide, set; - hide = $.hasClass(this, 'hide-announcement-button'); - set = function(hiddenPSAList) { - if (hide) { - return hiddenPSAList[g.SITE.ID] = PSAHiding.text; - } else { - return delete hiddenPSAList[g.SITE.ID]; - } - }; - set(Conf['hiddenPSAList']); - PSAHiding.sync(Conf['hiddenPSAList']); - return $.get('hiddenPSAList', Conf['hiddenPSAList'], function(arg) { - var hiddenPSAList; - hiddenPSAList = arg.hiddenPSAList; - set(hiddenPSAList); - return $.set('hiddenPSAList', hiddenPSAList); - }); - }, - sync: function(hiddenPSAList) { - var content, psa, ref; - psa = PSAHiding.psa, content = PSAHiding.content; - psa.hidden = hiddenPSAList[g.SITE.ID] === PSAHiding.text; - if (psa.hidden) { - $.add(content, slice.call(psa.childNodes)); - } else { - $.add(psa, slice.call(content.childNodes)); - } - return (ref = PSAHiding.hr) != null ? ref.hidden = psa.hidden : void 0; - } - }; - - return PSAHiding; - -}).call(this); - -PassMessage = (function() { - var PassMessage; - - PassMessage = { - init: function() { - var close, msg; - if (Conf['passMessageClosed']) { - return; - } - msg = $.el('div', { - className: 'box-outer top-box' - }, {innerHTML: "

      Trouble buying a 4chan Pass? (a message from 4chan X) ×

      Check the 4chan X wiki for alternative solutions.
      "}); - msg.style.cssText = 'padding-bottom: 0;'; - close = $('a', msg); - $.on(close, 'click', function() { - $.rm(msg); - return $.set('passMessageClosed', true); - }); - return $.ready(function() { - var hd; - if ((hd = $.id('hd'))) { - return $.after(hd, msg); - } else { - return $.prepend(d.body, msg); - } - }); - } - }; - - return PassMessage; - -}).call(this); - -PostJumper = (function() { - var PostJumper; - - PostJumper = { - init: function() { - var ref; - if (!(Conf['Unique ID and Capcode Navigation'] && ((ref = g.VIEW) === 'index' || ref === 'thread'))) { - return; - } - this.buttons = this.makeButtons(); - return Callbacks.Post.push({ - name: 'Post Jumper', - cb: this.node - }); - }, - node: function() { - var buttons, i, len, ref; - if (this.isClone) { - ref = $$('.postJumper', this.nodes.info); - for (i = 0, len = ref.length; i < len; i++) { - buttons = ref[i]; - PostJumper.addListeners(buttons); - } - return; - } - if (this.nodes.uniqueIDRoot) { - PostJumper.addButtons(this, 'uniqueID'); - } - if (this.nodes.capcode) { - return PostJumper.addButtons(this, 'capcode'); - } - }, - addButtons: function(post, type) { - var buttons, value; - value = post.info[type]; - buttons = PostJumper.buttons.cloneNode(true); - $.extend(buttons.dataset, { - type: type, - value: value - }); - $.after(post.nodes[type + (type === 'capcode' ? '' : 'Root')], buttons); - return PostJumper.addListeners(buttons); - }, - addListeners: function(buttons) { - $.on(buttons.firstChild, 'click', PostJumper.buttonClick); - return $.on(buttons.lastChild, 'click', PostJumper.buttonClick); - }, - buttonClick: function() { - var dir, toJumper; - dir = $.hasClass(this, 'prev') ? -1 : 1; - if ((toJumper = PostJumper.find(this.parentNode, dir))) { - return PostJumper.scroll(this.parentNode, toJumper); - } - }, - find: function(jumper, dir) { - var axis, jumper2, ref, type, value, xpath; - ref = jumper.dataset, type = ref.type, value = ref.value; - xpath = "span[contains(@class,\"postJumper\") and @data-value=\"" + value + "\" and @data-type=\"" + type + "\"]"; - axis = dir < 0 ? 'preceding' : 'following'; - jumper2 = jumper; - while ((jumper2 = $.x(axis + "::" + xpath, jumper2))) { - if (jumper2.getBoundingClientRect().height) { - return jumper2; - } - } - if ((jumper2 = $.x("(//" + xpath + ")[" + (dir < 0 ? 'last()' : '1') + "]"))) { - if (jumper2.getBoundingClientRect().height) { - return jumper2; - } - } - while ((jumper2 = $.x(axis + "::" + xpath, jumper2)) && jumper2 !== jumper) { - if (jumper2.getBoundingClientRect().height) { - return jumper2; - } - } - return null; - }, - makeButtons: function() { - var charNext, charPrev, classNext, classPrev, span; - charPrev = '\u23EB'; - charNext = '\u23EC'; - classPrev = 'prev'; - classNext = 'next'; - span = $.el('span', { - className: 'postJumper' - }); - $.extend(span, {innerHTML: "" + E(charPrev) + "" + E(charNext) + ""}); - return span; - }, - scroll: function(fromJumper, toJumper) { - var destPos, prevPos; - prevPos = fromJumper.getBoundingClientRect().top; - destPos = toJumper.getBoundingClientRect().top; - return window.scrollBy(0, destPos - prevPos); - } - }; - - return PostJumper; - -}).call(this); - -RelativeDates = (function() { - var RelativeDates, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - RelativeDates = { - INTERVAL: $.MINUTE / 2, - init: function() { - var ref; - if (((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Relative Post Dates'] && !Conf['Relative Date Title'] || Index.enabled) { - this.flush(); - $.on(d, 'visibilitychange PostsInserted', this.flush); - } - if (Conf['Relative Post Dates']) { - return Callbacks.Post.push({ - name: 'Relative Post Dates', - cb: this.node - }); - } - }, - node: function() { - var dateEl; - if (!this.info.date) { - return; - } - dateEl = this.nodes.date; - if (Conf['Relative Date Title']) { - $.on(dateEl, 'mouseover', (function(_this) { - return function() { - return RelativeDates.hover(_this); - }; - })(this)); - return; - } - if (this.isClone) { - return; - } - dateEl.title = dateEl.textContent; - return RelativeDates.update(this); - }, - relative: function(diff, now, date, abbrev) { - var days, months, number, rounded, unit, years; - unit = (number = diff / $.DAY) >= 1 ? (years = now.getFullYear() - date.getFullYear(), months = now.getMonth() - date.getMonth(), days = now.getDate() - date.getDate(), years > 1 ? (number = years - (months < 0 || months === 0 && days < 0), 'year') : years === 1 && (months > 0 || months === 0 && days >= 0) ? (number = years, 'year') : (months = months + 12 * years) > 1 ? (number = months - (days < 0), 'month') : months === 1 && days >= 0 ? (number = months, 'month') : 'day') : (number = diff / $.HOUR) >= 1 ? 'hour' : (number = diff / $.MINUTE) >= 1 ? 'minute' : (number = Math.max(0, diff) / $.SECOND, 'second'); - rounded = Math.round(number); - if (abbrev) { - unit = unit === 'month' ? 'mo' : unit[0]; - } else { - if (rounded !== 1) { - unit += 's'; - } - } - if (abbrev) { - return "" + rounded + unit; - } else { - return rounded + " " + unit + " ago"; - } - }, - stale: [], - flush: function() { - var data, i, len, now, ref; - if (d.hidden) { - return; - } - now = new Date(); - ref = RelativeDates.stale; - for (i = 0, len = ref.length; i < len; i++) { - data = ref[i]; - RelativeDates.update(data, now); - } - RelativeDates.stale = []; - clearTimeout(RelativeDates.timeout); - return RelativeDates.timeout = setTimeout(RelativeDates.flush, RelativeDates.INTERVAL); - }, - hover: function(post) { - var date, diff, now; - date = post.info.date; - now = new Date(); - diff = now - date; - return post.nodes.date.title = RelativeDates.relative(diff, now, date); - }, - update: function(data, now) { - var abbrev, date, diff, i, isPost, len, ref, relative, singlePost; - isPost = data instanceof Post; - if (isPost) { - date = data.info.date; - abbrev = false; - } else { - date = new Date(+data.dataset.utc); - abbrev = !!data.dataset.abbrev; - } - now || (now = new Date()); - diff = now - date; - relative = RelativeDates.relative(diff, now, date, abbrev); - if (isPost) { - ref = [data].concat(data.clones); - for (i = 0, len = ref.length; i < len; i++) { - singlePost = ref[i]; - singlePost.nodes.date.firstChild.textContent = relative; - } - } else { - data.firstChild.textContent = relative; - } - return RelativeDates.setOwnTimeout(diff, data); - }, - setOwnTimeout: function(diff, data) { - var delay; - delay = diff < $.MINUTE ? $.SECOND - (diff + $.SECOND / 2) % $.SECOND : diff < $.HOUR ? $.MINUTE - (diff + $.MINUTE / 2) % $.MINUTE : diff < $.DAY ? $.HOUR - (diff + $.HOUR / 2) % $.HOUR : $.DAY - (diff + $.DAY / 2) % $.DAY; - return setTimeout(RelativeDates.markStale, delay, data); - }, - markStale: function(data) { - if (indexOf.call(RelativeDates.stale, data) >= 0) { - return; - } - if (data instanceof Post && !g.posts.get(data.fullID)) { - return; - } - if (data instanceof Element && !doc.contains(data)) { - return; - } - return RelativeDates.stale.push(data); - } - }; - - return RelativeDates; - -}).call(this); - -RemoveSpoilers = (function() { - var RemoveSpoilers, - slice = [].slice; - - RemoveSpoilers = { - init: function() { - if (Conf['Reveal Spoilers']) { - $.addClass(doc, 'reveal-spoilers'); - } - if (!Conf['Remove Spoilers']) { - return; - } - Callbacks.Post.push({ - name: 'Reveal Spoilers', - cb: this.node - }); - if (g.VIEW === 'archive') { - return $.ready(function() { - return RemoveSpoilers.unspoiler($.id('arc-list')); - }); - } - }, - node: function() { - return RemoveSpoilers.unspoiler(this.nodes.comment); - }, - unspoiler: function(el) { - var i, len, span, spoiler, spoilers; - spoilers = $$(g.SITE.selectors.spoiler, el); - for (i = 0, len = spoilers.length; i < len; i++) { - spoiler = spoilers[i]; - span = $.el('span', { - className: 'removed-spoiler' - }); - $.replace(spoiler, span); - $.add(span, slice.call(spoiler.childNodes)); - } - } - }; - - return RemoveSpoilers; - -}).call(this); - -Report = (function() { - var Report; - - Report = { - init: function() { - var match; - if (!(match = location.search.match(/\bno=(\d+)/))) { - return; - } - Captcha.replace.init(); - this.postID = +match[1]; - return $.ready(this.ready); - }, - ready: function() { - $.addStyle(CSS.report); - if (Conf['Archive Report']) { - Report.archive(); - } - new MutationObserver(function() { - Report.fit('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return Report.fit('body'); - }).observe(d.body, { - childList: true, - attributes: true, - subtree: true - }); - return Report.fit('body'); - }, - fit: function(selector) { - var dy, el; - if (!((el = $(selector, doc)) && getComputedStyle(el).visibility !== 'hidden')) { - return; - } - dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8; - if (dy > 0) { - return window.resizeBy(0, dy); - } - }, - archive: function() { - var enabled, fieldset, form, match, message, reason, submit, types, urls; - if (!(urls = Redirect.report(g.BOARD.ID)).length) { - return; - } - form = $('form'); - types = $.id('reportTypes'); - message = $('h3'); - fieldset = $.el('fieldset', { - id: 'archive-report', - hidden: true - }, {innerHTML: ""}); - enabled = $('#archive-report-enabled', fieldset); - reason = $('#archive-report-reason', fieldset); - submit = $('#archive-report-submit', fieldset); - $.on(enabled, 'change', function() { - return reason.disabled = !this.checked; - }); - if (form && types) { - fieldset.hidden = !$('[value="31"]', types).checked; - $.on(types, 'change', function(e) { - fieldset.hidden = e.target.value !== '31'; - return Report.fit('body'); - }); - $.after(types, fieldset); - Report.fit('body'); - $.one(form, 'submit', function(e) { - if (!fieldset.hidden && enabled.checked) { - e.preventDefault(); - return Report.archiveSubmit(urls, reason.value, (function(_this) { - return function(results) { - _this.action = '#archiveresults=' + encodeURIComponent(JSON.stringify(results)); - return _this.submit(); - }; - })(this)); - } - }); - } else if (message) { - fieldset.hidden = /Report submitted!/.test(message.textContent); - $.on(enabled, 'change', function() { - return submit.hidden = !this.checked; - }); - $.after(message, fieldset); - $.on(submit, 'click', function() { - return Report.archiveSubmit(urls, reason.value, Report.archiveResults); - }); - } - if ((match = location.hash.match(/^#archiveresults=(.*)$/))) { - try { - return Report.archiveResults(JSON.parse(decodeURIComponent(match[1]))); - } catch (error) {} - } - }, - archiveSubmit: function(urls, reason, cb) { - var fn, form, i, len, name, ref, results, url; - form = $.formData({ - board: g.BOARD.ID, - num: Report.postID, - reason: reason - }); - results = []; - fn = function(name, url) { - return $.ajax(url, { - onloadend: function() { - results.push([ - name, this.response || { - error: '' - } - ]); - if (results.length === urls.length) { - return cb(results); - } - }, - form: form - }); - }; - for (i = 0, len = urls.length; i < len; i++) { - ref = urls[i], name = ref[0], url = ref[1]; - fn(name, url); - } - }, - archiveResults: function(results) { - var fieldset, i, len, line, name, ref, response; - fieldset = $.id('archive-report'); - for (i = 0, len = results.length; i < len; i++) { - ref = results[i], name = ref[0], response = ref[1]; - line = $.el('h3', { - className: 'archive-report-response' - }); - if ('success' in response) { - $.addClass(line, 'archive-report-success'); - line.textContent = name + ": " + response.success; - } else { - $.addClass(line, 'archive-report-error'); - line.textContent = name + ": " + (response.error || 'Error reporting post.'); - } - if (fieldset) { - $.before(fieldset, line); - } else { - $.add(d.body, line); - } - } - } - }; - - return Report; - -}).call(this); - -ThreadLinks = (function() { - var ThreadLinks; - - ThreadLinks = { - init: function() { - if (!(g.VIEW === 'index' && Conf['Open Threads in New Tab'])) { - return; - } - Callbacks.Post.push({ - name: 'Thread Links', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Thread Links', - cb: this.catalogNode - }); - }, - node: function() { - if (this.isReply || this.isClone) { - return; - } - return ThreadLinks.process(this.nodes.reply); - }, - catalogNode: function() { - return ThreadLinks.process(this.nodes.thumb.parentNode); - }, - process: function(link) { - return link.target = '_blank'; - } - }; - - return ThreadLinks; - -}).call(this); - -Time = (function() { - var Time; - - Time = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread' || ref === 'archive') && Conf['Time Formatting'])) { - return; - } - return Callbacks.Post.push({ - name: 'Time Formatting', - cb: this.node - }); - }, - node: function() { - var textContent; - if (!this.info.date || this.isClone) { - return; - } - textContent = this.nodes.date.textContent; - return this.nodes.date.textContent = textContent.match(/^\s*/)[0] + Time.format(Conf['time'], this.info.date) + textContent.match(/\s*$/)[0]; - }, - format: function(formatString, date) { - return formatString.replace(/%(.)/g, function(s, c) { - if ($.hasOwn(Time.formatters, c)) { - return Time.formatters[c].call(date); - } else { - return s; - } - }); - }, - day: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], - month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - localeFormat: function(date, options, defaultValue) { - if (Conf['timeLocale']) { - try { - return Intl.DateTimeFormat(Conf['timeLocale'], options).format(date); - } catch (error) {} - } - return defaultValue; - }, - localeFormatPart: function(date, options, part, defaultValue) { - var parts; - if (Conf['timeLocale']) { - try { - parts = Intl.DateTimeFormat(Conf['timeLocale'], options).formatToParts(date); - return parts.map(function(x) { - if (x.type === part) { - return x.value; - } else { - return ''; - } - }).join(''); - } catch (error) {} - } - return defaultValue; - }, - zeroPad: function(n) { - if (n < 10) { - return "0" + n; - } else { - return n; - } - }, - formatters: { - a: function() { - return Time.localeFormat(this, { - weekday: 'short' - }, Time.day[this.getDay()].slice(0, 3)); - }, - A: function() { - return Time.localeFormat(this, { - weekday: 'long' - }, Time.day[this.getDay()]); - }, - b: function() { - return Time.localeFormat(this, { - month: 'short' - }, Time.month[this.getMonth()].slice(0, 3)); - }, - B: function() { - return Time.localeFormat(this, { - month: 'long' - }, Time.month[this.getMonth()]); - }, - d: function() { - return Time.zeroPad(this.getDate()); - }, - e: function() { - return this.getDate(); - }, - H: function() { - return Time.zeroPad(this.getHours()); - }, - I: function() { - return Time.zeroPad(this.getHours() % 12 || 12); - }, - k: function() { - return this.getHours(); - }, - l: function() { - return this.getHours() % 12 || 12; - }, - m: function() { - return Time.zeroPad(this.getMonth() + 1); - }, - M: function() { - return Time.zeroPad(this.getMinutes()); - }, - p: function() { - return Time.localeFormatPart(this, { - hour: 'numeric', - hour12: true - }, 'dayperiod', (this.getHours() < 12 ? 'AM' : 'PM')); - }, - P: function() { - return Time.formatters.p.call(this).toLowerCase(); - }, - S: function() { - return Time.zeroPad(this.getSeconds()); - }, - y: function() { - return this.getFullYear().toString().slice(2); - }, - Y: function() { - return this.getFullYear(); - }, - '%': function() { - return '%'; - } - } - }; - - return Time; - -}).call(this); - -Tinyboard = (function() { - var Tinyboard; - - Tinyboard = { - init: function() { - if (g.SITE.software !== 'tinyboard') { - return; - } - if (g.VIEW === 'thread') { - return Main.ready(function() { - return $.global(function() { - var base, boardID, form, originalNoko, ref, ref1, ref2, threadID; - ref = document.currentScript.dataset, boardID = ref.boardID, threadID = ref.threadID; - threadID = +threadID; - form = document.querySelector('form[name="post"]'); - window.$(document).ajaxComplete(function(event, request, settings) { - var detail, noko, postID, redirect, ref1, ref2; - if (settings.url !== form.action) { - return; - } - if (!(postID = +((ref1 = request.responseJSON) != null ? ref1.id : void 0))) { - return; - } - detail = { - boardID: boardID, - threadID: threadID, - postID: postID - }; - try { - ref2 = request.responseJSON, redirect = ref2.redirect, noko = ref2.noko; - if (redirect && (typeof originalNoko !== "undefined" && originalNoko !== null) && !originalNoko && !noko) { - detail.redirect = redirect; - } - } catch (error) {} - event = new CustomEvent('QRPostSuccessful', { - bubbles: true, - detail: detail - }); - return document.dispatchEvent(event); - }); - originalNoko = (ref1 = window.tb_settings) != null ? (ref2 = ref1.ajax) != null ? ref2.always_noko_replies : void 0 : void 0; - return ((base = (window.tb_settings || (window.tb_settings = {}))).ajax || (base.ajax = {})).always_noko_replies = true; - }, { - boardID: g.BOARD.ID, - threadID: g.THREADID - }); - }); - } - } - }; - - return Tinyboard; - -}).call(this); - -Favicon = (function() { - var Favicon; - - Favicon = { - init: function() { - return $.asap((function() { - return d.head && (Favicon.el = $('link[rel="shortcut icon"]', d.head)); - }), Favicon.initAsap); - }, - set: function(status) { - Favicon.status = status; - if (Favicon.el) { - Favicon.el.href = Favicon[status]; - return $.add(d.head, Favicon.el); - } - }, - initAsap: function() { - var href; - Favicon.el.type = 'image/x-icon'; - href = Favicon.el.href; - Favicon.isSFW = /ws\.ico$/.test(href); - Favicon["default"] = href; - Favicon["switch"](); - if (Favicon.status) { - return Favicon.set(Favicon.status); - } - }, - "switch": function() { - var f, i, items, t; - items = { - ferongr: ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///9zBQC/AADpDAP/gID/q6voCwJJTwpOAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxUlEQVR42q1TOwrCQBB9s0FRtJI0WoqFtSLYegoP4gVSeJsUHsHSI3iFeIqRXXgwrhlXwYHHhLwPTB7B36abBCV+0pA4DUBQUNZYQptGtW3jtoKyxgoe0yrBCoyZfL/5ioQ3URZOXW9I341l3oo+NXEZiW4CEuIzvPECopED4OaZ3RNmeAm4u+a8Jr5f17VyVoL8fr8qcltzwlyyj2iqcgPOQ9ExkHAITgD75bYBe0A5S4H/P9htuWMF3QXoQpwaKeT+lnsC6JE5I6aq6fEAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///8AcH4AtswA2PJ55fKi6fIA1/FtpPADAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxElEQVQ4y2NgoBq4/vE/HJOsBiRQUIfA2AzBqQYqUfn00/9FLz+BaQxDCKqBmX7jExijKEDSDJPHrnnbGQhGV4RmOFwdVkNwhQMheYwQxhaIi7b9Z9A3gWAQm2BUoQOgRhgA8o7j1ozLC4LCyAZcx6kZI5qg4kLKqggDFFWxJySsUQVzlb4pwgAJaTRvokcVNgOqOv8zcHBCsL07DgNg8YsczzA5MxtUL+DMD8g0slxI/H8GQ/P/DJKyeKIRpglXZsIiBwBhP5O+VbI/JgAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEX///8oeQBJ3ABV/wHM/7Lu/+ZU/gAqUP3dAAAAAXRSTlMAQObYZgAAAGJJREFUeF5Fi7ENg0AQBCfa/AFdDh2gdwPIogMK2E2+/xLslwOvdqRJhv+GQQPUCtJM7svankLrq/I+TY5e6Ueh1jyBMX7AFJi9vwfyVO4CbbO6jNYpp9GyVPbdkFhVgAQ2H0NOE5jk9DT8AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAx0lEQVQ4y2NgoBYI+cfwH4ZJVgMS0KhEYGyG4FQDkzjzf9P/d/+fgWl0QwiqgSkI/c8IxsgKkDXD5LFq9rwDweiK0A2HqcNqCK5wICSPEcLYAtH+AMN/IXMIBrEJRie6OEgjDAC5x3FqxuUFNiEUA67j1IweTTBxBQ1puAG86jgSEraogskJWSBcwCGF5k30qMJmgMFEhv/MXBAs5oLDAFj8IsczTE7UEeECbhU8+QGZRpaTi2b4L2zF8J9TGk80wjThykzY5AAW/2O1C2mIbgAAAABJRU5ErkJggg=='], - 'xat-': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAG1BMVEX+AACLkZFub2yfaF3zZGIAAAD/AAD/iYr/zs8IPcF6AAAABXRSTlMAeprJ7xzg6IEAAABZSURBVAjXY2DABKGBSkqioQwMrGmpxsZhaQEMDGFpIa5pqSCRtPDSNJBIaGh5eShQDYOye0V7iREKAyQFYoiCFAcyILQDGcGmEEZYkGoqiMHKysAQEICwGwAAjBmBqhYlagAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAPFBMVEUAAACEgoBva2ilamDxcG7IaWYgFBNOSEf//f0PDQwBAAA7LCwAAAD/AAD+hIX+m5z+zc5HAADPAAAGAADl032uAAAADHRSTlMAzNv0/vz+6v3+7ALrmfyXAAAAaUlEQVQY042PyxKAIAhFAc1eV7T6/3/N8VXOtAgWwBm4ANEPA8AswpySXHvvYZLlpBNrh9pDtcSqAQ1BUTVIjNUQY5icmwfglmXNgE0d6QBF9GigrU0A9LoM53U1kFzk6SBQuWfD/vHqDUCpBmVKTTM4AAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIVBMVEUAAACRjop4dXVpZ2tdcI9dfKdisfMAAAAumMN9xv+s2/+PADT2AAAAB3RSTlMAepGdv83v3HIc4QAAAFxJREFUCNdjYMAE5YXKRuLlDAzsHe2uIRUdBQwMFR1l6R3tIJGOyukdIJHy8lkry4FqGEwzV62aFozMUAFJOQEZ4iDFhQwI7UBGaTiEUVFs3g5isLMzMBQUIOwGAJRlIu9hk08QAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAMFBMVEUAAACAgYVlc4ljsu4AAAAAAAAAAAAumMODyP6b1P6e1f/g8v89msgSIiwNFxwbPU3tQYj5AAAABnRSTlMAxej+9VTmD9ciAAAAZElEQVQI12NgwARpiUKKYmkMDGzlZUpK6eUJDAzp5clm5WUgkfKMtnKQSFpa54o0oBoGJYvZO88+gjJu7wMyhIBS2SCGGFDxaxADpP32NjAjSe0bSFd6epIaWISNjYEhJRVhNwAGlyJpYtcvcAAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAHlBMVEUfJSCRi5Frbm9dn19082KR/30AAABmzDOq/5vZ/9Gt/vt2AAAABnRSTlMAe5rJ7/4vxEp4AAAAWUlEQVQI12NgwARpiUpKYmkMDGzlZcbG6eUJDAzp5Slu5WUgkfLUsHKQSFpaRGsaUA2DsmvnjBAjFAZICsQQAylOZEBoBzKSzSCM9CS1MhCDjY2BISEBYTcAtgAcKSK2vuIAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAM1BMVEUAAACBj39tfm1qj2RepFlu2VQAAQAAAAAAAABmyzOX/oSr/pus/pzk/98PGgtatC4CBAI1ENblAAAACHRSTlMA09/p9v77ig0SBcQAAABnSURBVBjTjY9LDsAgCEQRsR2xWu9/2hK/adJFYQG8wABEPwyAYzNnSatjjPAiviWLhPCqI1R7HBrQdCmGBrEETTmnUAq/QMm5dODHyAQOXXR1zLUGsIEI7lonMGfeHQTq9xw4P159AIxSBSC53km7AAAAAElFTkSuQmCC'], - Mayhem: ['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'], - '4chanJS': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAD/AABnZ2f///8nFk05AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEUAAAAAAAD/AABmZmYA/wBD99DBAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE9JREFUCNdljcsRACEIQ5MOiNKAdGAJ9N/Uiu7nsMzABHgB4B8ygFoZA2hhVWavhhGeURPJU9q45+17hGbfGxa82Ndex3hEM44SJGD2/b4AzDgGlHbl388AAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAD1BMVEUBAAAAAAAul8NnZ2f////82iC9AAAAAXRSTlMAQObYZgAAAEFJREFUeNqNjgEKACAMAjvX/98cAkkxgmSgO8Bt/Ai4ApJ6KKhzF3OiEMDASrGB/QWgPEHsUpN+Ng9xAETMYhDrWmeHAMcmvycWAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEUAAAAAAAAul8NnZ2f/AAD7B+mqAAAAAXRSTlMAQObYZgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAE9JREFUCNdljcsRACEIQ5MOiNKAdGAJ9N/Uiu7nsMzABHgB4B8ygFoZA2hhVWavhhGeURPJU9q45+17hGbfGxa82Ndex3hEM44SJGD2/b4AzDgGlHbl388AAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAElBMVEUBAAAAAABmzDNlyjJnZ2f///+6o7dfAAAAAXRSTlMAQObYZgAAAERJREFUeF6NjkEKADEIA51o///lJZfQxUsHITogWi8AvwZJuxmYa25xDooBLEwOWFTYAsYVhdorLZt9Ng9xCUTCUCQ2H3F4ANrZ2WNiAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEUAAAAAAABmzDNmZmb/AAC8/wCMAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAE9JREFUCNdljcsRACEIQ5MOiNKAdGAJ9N/Uiu7nsMzABHgB4B8ygFoZA2hhVWavhhGeURPJU9q45+17hGbfGxa82Ndex3hEM44SJGD2/b4AzDgGlHbl388AAAAASUVORK5CYII='], - Original: ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX/////AAD///8AAABBZmS3AAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhElEQVR42q1RwQnAMAjMu5M4guAKXa4j5dUROo5tipSDcrFChUONd0di2m/hEGVOHDyIPufgwAFASDkpoSzmBrkJ2UMyR9LsJ3rvrqo3Rt1YMIMhhNnOxLMnoMFBxHyJAr2IOBFzA8U+6pLBdmEJTA0aMVjpDd6Loks0s5HZNwYx8tfZCZ0kll7ORffZAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX///8ul8P///8AAACaqgkzAAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAALVBMVEUAAAAAAAAAAAAAAAABBQcHFx4KISoNLToaVW4oKCgul8M4ODg7OzvBwcH///8uS/CdAAAAA3RSTlMAx9dmesIgAAAAV0lEQVR42m2NWw6AIBAD1eILZO5/XI0UAgm7H9tOsu0yGWAQSOoFijHOxOANGqm/LczpOaXs4gISrPZ+gc2+hO5w2xdwgOjBFUIF+sEJrhUl9JFr+badFwR+BfqlmGUJAAAAAElFTkSuQmCC', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEX///9mzDP///8AAACT0n1lAAAAAXRSTlMAQObYZgAAAExJREFUeF4tyrENgDAMAMFXKuQswQLBG3mOlBnFS1gwDfIYLpEivvjq2MlqjmYvYg5jWEzCwtDSQlwcXKCVLrpFbvLvvSf9uZJ2HusDtJAY7Tkn1oYAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAALVBMVEUAAAAAAAAAAAAAAAAECAIQIAgWLAsePA8oKCg4ODg6dB07OztmzDPBwcH///+rsf3XAAAAA3RSTlMAx9dmesIgAAAAV0lEQVR42m2NWw6AIBAD1eIDhbn/cTVSCCTsfmw7ybbLZIBBIKkXKKU0E4M3aKT+tjCn5xiziwuIsNr7BTb7ErrDZV/AAaIHdwgV6AcnuFaU0Eeu5dt2XiUyBjCQ2bIrAAAAAElFTkSuQmCC'], - 'Metro': ['iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAC/AABrZQDiAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAAC/AAD///8dAAApAABsAAAHAAA4AACQAAAsAABMCpCvAAAAA3RSTlMAPse+s4iwAAAAMklEQVQI12NggAFmY2MDECaNAQZCilAzVJyg5oS4GqAxUtygjIp2KGOKJ5SxepcB3BUAcdYRqxAtgFoAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAAA1/GhpCidAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAAAA1/H///8AISUALzQAeokACAkAQEcAorYAMTcE9WFNAAAAA3RSTlMAPse+s4iwAAAAMklEQVQI12NggAFmY2MDECaNAQZCilAzVJyg5oS4GqAxUtygjIp2KGOKJ5SxepcB3BUAcdYRqxAtgFoAAAAASUVORK5CYII=', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAABV/wErM5hwAAAAAXRSTlMAQObYZgAAABJJREFUCB1jZGBgrMNAQEEc4gCSfAX5bRw/NQAAAABJRU5ErkJggg==', 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAAAAAAAAABV/wH///8NKAASOAAwkQADCgAZTABAwQATOwC5e3VGAAAAA3RSTlMAPse+s4iwAAAAMklEQVQI12NggAFmY2MDECaNAQZCilAzVJyg5oS4GqAxUtygjIp2KGOKJ5SxepcB3BUAcdYRqxAtgFoAAAAASUVORK5CYII='] - }; - items = $.getOwn(items, Conf['favicon']); - f = Favicon; - t = 'data:image/png;base64,'; - i = 0; - while (items[i]) { - items[i] = t + items[i++]; - } - f.unreadDead = items[0], f.unreadDeadY = items[1], f.unreadSFW = items[2], f.unreadSFWY = items[3], f.unreadNSFW = items[4], f.unreadNSFWY = items[5]; - return f.update(); - }, - update: function() { - if (this.isSFW) { - this.unread = this.unreadSFW; - return this.unreadY = this.unreadSFWY; - } else { - this.unread = this.unreadNSFW; - return this.unreadY = this.unreadNSFWY; - } - }, - SFW: '//s.4cdn.org/image/favicon-ws.ico', - NSFW: '//s.4cdn.org/image/favicon.ico', - dead: 'data:image/gif;base64,R0lGODlhEAAQAKECAAAAAP8AAP///////yH5BAEKAAIALAAAAAAQABAAAAIvlI+pq+D9DAgUoFkPDlbs7lFZKIJOJJ3MyraoB14jFpOcVMpzrnF3OKlZYsMWowAAOw==', - logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACAAgMAAAC+UIlYAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAGlJREFUWMPtlkEKADEIA/tJP9lXLttQto2yHxgDHozTi0ToGK2WKZZ+HAQQMZc+xBwI4EZ+wAC2IfPuSIDOZJrSZQEAX9eVJhhwIuUYAnQe8rhAEMAZlTI2MID9f5Clyh0JeE1V1ZEAvB4qDfwuJTSGRAAAAABJRU5ErkJggg==' - }; - - return Favicon; - -}).call(this); - -MarkNewIPs = (function() { - var MarkNewIPs; - - MarkNewIPs = { - init: function() { - if (!(g.SITE.software === 'yotsuba' && g.VIEW === 'thread' && Conf['Mark New IPs'])) { - return; - } - return Callbacks.Thread.push({ - name: 'Mark New IPs', - cb: this.node - }); - }, - node: function() { - MarkNewIPs.ipCount = this.ipCount; - MarkNewIPs.postCount = this.posts.keys.length; - return $.on(d, 'ThreadUpdate', MarkNewIPs.onUpdate); - }, - onUpdate: function(e) { - var deletedPosts, fullID, i, ipCount, j, k, len, len1, newPosts, postCount, ref; - ref = e.detail, ipCount = ref.ipCount, postCount = ref.postCount, newPosts = ref.newPosts, deletedPosts = ref.deletedPosts; - if (ipCount == null) { - return; - } - switch (ipCount - MarkNewIPs.ipCount) { - case postCount - MarkNewIPs.postCount + deletedPosts.length: - i = MarkNewIPs.ipCount; - for (j = 0, len = newPosts.length; j < len; j++) { - fullID = newPosts[j]; - MarkNewIPs.markNew(g.posts.get(fullID), ++i); - } - break; - case -deletedPosts.length: - for (k = 0, len1 = newPosts.length; k < len1; k++) { - fullID = newPosts[k]; - MarkNewIPs.markOld(g.posts.get(fullID)); - } - } - MarkNewIPs.ipCount = ipCount; - return MarkNewIPs.postCount = postCount; - }, - markNew: function(post, ipCount) { - var counter, suffix; - suffix = (Math.floor(ipCount / 10)) % 10 === 1 ? 'th' : ['st', 'nd', 'rd'][ipCount % 10 - 1] || 'th'; - counter = $.el('span', { - className: 'ip-counter', - textContent: "(" + ipCount + ")" - }); - post.nodes.nameBlock.title = "This is the " + ipCount + suffix + " IP in the thread."; - $.add(post.nodes.nameBlock, [$.tn(' '), counter]); - return $.addClass(post.nodes.root, 'new-ip'); - }, - markOld: function(post) { - post.nodes.nameBlock.title = 'Not the first post from this IP.'; - return $.addClass(post.nodes.root, 'old-ip'); - } - }; - - return MarkNewIPs; - -}).call(this); - -ReplyPruning = (function() { - var ReplyPruning; - - ReplyPruning = { - init: function() { - var el, label; - if (!(g.VIEW === 'thread' && Conf['Reply Pruning'])) { - return; - } - this.container = $.frag(); - this.summary = $.el('span', { - hidden: true, - className: 'summary' - }); - this.summary.style.cursor = 'pointer'; - $.on(this.summary, 'click', (function(_this) { - return function() { - _this.inputs.enabled.checked = !_this.inputs.enabled.checked; - return $.event('change', null, _this.inputs.enabled); - }; - })(this)); - label = UI.checkbox('Prune Replies', 'Show Last', Conf['Prune All Threads']); - el = $.el('span', { - title: 'Maximum number of replies to show.' - }, {innerHTML: " "}); - $.prepend(el, label); - this.inputs = { - enabled: label.firstElementChild, - replies: el.lastElementChild - }; - this.setEnabled.call(this.inputs.enabled); - $.on(this.inputs.enabled, 'change', this.setEnabled); - $.on(this.inputs.replies, 'change', $.cb.value); - Header.menu.addEntry({ - el: el, - order: 190 - }); - return Callbacks.Thread.push({ - name: 'Reply Pruning', - cb: this.node - }); - }, - position: 0, - hidden: 0, - hiddenFiles: 0, - total: 0, - totalFiles: 0, - setEnabled: function() { - var other; - other = QuoteThreading.input; - if (this.checked && (other != null ? other.checked : void 0)) { - other.checked = false; - $.event('change', null, other); - } - return ReplyPruning.active = this.checked; - }, - showIfHidden: function(id) { - if (ReplyPruning.container && $("#" + id, ReplyPruning.container)) { - ReplyPruning.inputs.enabled.checked = false; - return $.event('change', null, ReplyPruning.inputs.enabled); - } - }, - node: function() { - var ref; - ReplyPruning.thread = this; - if (this.isSticky) { - ReplyPruning.active = ReplyPruning.inputs.enabled.checked = true; - if (QuoteThreading.input) { - Conf['Thread Quotes'] = QuoteThreading.input.checked = false; - } - } - this.posts.forEach(function(post) { - if (post.isReply) { - ReplyPruning.total++; - if (post.file) { - return ReplyPruning.totalFiles++; - } - } - }); - if (ReplyPruning.active && /^#p\d+$/.test(location.hash) && (1 <= (ref = this.posts.keys.indexOf(location.hash.slice(2))) && ref < 1 + Math.max(ReplyPruning.total - +Conf["Max Replies"], 0))) { - ReplyPruning.active = ReplyPruning.inputs.enabled.checked = false; - } - $.after(this.OP.nodes.root, ReplyPruning.summary); - $.on(ReplyPruning.inputs.enabled, 'change', ReplyPruning.update); - $.on(ReplyPruning.inputs.replies, 'change', ReplyPruning.update); - $.on(d, 'ThreadUpdate', ReplyPruning.updateCount); - $.on(d, 'ThreadUpdate', ReplyPruning.update); - return ReplyPruning.update(); - }, - updateCount: function(e) { - var fullID, i, len, ref; - if (e.detail[404]) { - return; - } - ref = e.detail.newPosts; - for (i = 0, len = ref.length; i < len; i++) { - fullID = ref[i]; - ReplyPruning.total++; - if (g.posts.get(fullID).file) { - ReplyPruning.totalFiles++; - } - } - }, - update: function() { - var boardTop, frag, hidden1, hidden2, node, oldPos, post, posts; - hidden1 = ReplyPruning.hidden; - hidden2 = ReplyPruning.active ? Math.max(ReplyPruning.total - +Conf["Max Replies"], 0) : 0; - oldPos = d.body.clientHeight - window.scrollY; - posts = ReplyPruning.thread.posts; - if (ReplyPruning.hidden < hidden2) { - while (ReplyPruning.hidden < hidden2 && ReplyPruning.position < posts.keys.length) { - post = posts.get(posts.keys[ReplyPruning.position++]); - if (post.isReply && !post.isFetchedQuote) { - while ((node = ReplyPruning.summary.nextSibling) && node !== post.nodes.root) { - $.add(ReplyPruning.container, node); - } - $.add(ReplyPruning.container, post.nodes.root); - ReplyPruning.hidden++; - if (post.file) { - ReplyPruning.hiddenFiles++; - } - } - } - } else if (ReplyPruning.hidden > hidden2) { - frag = $.frag(); - while (ReplyPruning.hidden > hidden2 && ReplyPruning.position > 0) { - post = posts.get(posts.keys[--ReplyPruning.position]); - if (post.isReply && !post.isFetchedQuote) { - while ((node = ReplyPruning.container.lastChild) && node !== post.nodes.root) { - $.prepend(frag, node); - } - $.prepend(frag, post.nodes.root); - ReplyPruning.hidden--; - if (post.file) { - ReplyPruning.hiddenFiles--; - } - } - } - $.after(ReplyPruning.summary, frag); - $.event('PostsInserted', null, ReplyPruning.summary.parentNode); - } - ReplyPruning.summary.textContent = ReplyPruning.active ? g.SITE.Build.summaryText('+', ReplyPruning.hidden, ReplyPruning.hiddenFiles) : g.SITE.Build.summaryText('-', ReplyPruning.total, ReplyPruning.totalFiles); - ReplyPruning.summary.hidden = ReplyPruning.total <= +Conf["Max Replies"]; - if (hidden1 !== hidden2 && (boardTop = Header.getTopOf($('.board'))) < 0) { - return window.scrollBy(0, Math.max(d.body.clientHeight - oldPos, window.scrollY + boardTop) - window.scrollY); - } - } - }; - - return ReplyPruning; - -}).call(this); - -ThreadStats = (function() { - var ThreadStats; - - ThreadStats = { - postCount: 0, - fileCount: 0, - postIndex: 0, - init: function() { - var base, sc, statsHTML, statsTitle; - if (g.VIEW !== 'thread' || !Conf['Thread Stats']) { - return; - } - if (Conf['Page Count in Stats']) { - this[(typeof (base = g.SITE).isPrunedByAge === "function" ? base.isPrunedByAge(g.BOARD) : void 0) ? 'showPurgePos' : 'showPage'] = true; - } - statsHTML = {innerHTML: "? / ?" + ((Conf["IP Count in Stats"] && g.SITE.hasIPCount) ? " / ?" : "") + ((Conf["Page Count in Stats"]) ? " / ?" : "")}; - statsTitle = 'Posts / Files'; - if (Conf['IP Count in Stats'] && g.SITE.hasIPCount) { - statsTitle += ' / IPs'; - } - if (Conf['Page Count in Stats']) { - statsTitle += (this.showPurgePos ? ' / Purge Position' : ' / Page'); - } - if (Conf['Updater and Stats in Header']) { - this.dialog = sc = $.el('span', { - id: 'thread-stats', - title: statsTitle - }); - $.extend(sc, statsHTML); - Header.addShortcut('stats', sc, 200); - } else { - this.dialog = sc = UI.dialog('thread-stats', {innerHTML: "
      " + (statsHTML).innerHTML + "
      "}); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.postCountEl = $('#post-count', sc); - this.fileCountEl = $('#file-count', sc); - this.ipCountEl = $('#ip-count', sc); - this.pageCountEl = $('#page-count', sc); - if (this.pageCountEl) { - $.on(this.pageCountEl, 'click', ThreadStats.fetchPage); - } - return Callbacks.Thread.push({ - name: 'Thread Stats', - cb: this.node - }); - }, - node: function() { - ThreadStats.thread = this; - ThreadStats.count(); - ThreadStats.update(); - ThreadStats.fetchPage(); - $.on(d, 'PostsInserted', function() { - return $.queueTask(ThreadStats.onPostsInserted); - }); - return $.on(d, 'ThreadUpdate', ThreadStats.onUpdate); - }, - count: function() { - var i, j, n, post, posts, ref, ref1; - posts = ThreadStats.thread.posts; - n = posts.keys.length; - for (i = j = ref = ThreadStats.postIndex, ref1 = n; j < ref1; i = j += 1) { - post = posts.get(posts.keys[i]); - if (!post.isFetchedQuote) { - ThreadStats.postCount++; - ThreadStats.fileCount += post.files.length; - } - } - return ThreadStats.postIndex = n; - }, - onUpdate: function(e) { - var fileCount, postCount, ref; - if (e.detail[404]) { - return; - } - ref = e.detail, postCount = ref.postCount, fileCount = ref.fileCount; - $.extend(ThreadStats, { - postCount: postCount, - fileCount: fileCount - }); - ThreadStats.postIndex = ThreadStats.thread.posts.keys.length; - ThreadStats.update(); - if (ThreadStats.showPage && ThreadStats.pageCountEl.textContent !== '1') { - return ThreadStats.fetchPage(); - } - }, - onPostsInserted: function() { - if (!(ThreadStats.thread.posts.keys.length > ThreadStats.postIndex)) { - return; - } - ThreadStats.count(); - ThreadStats.update(); - if (ThreadStats.showPage && ThreadStats.pageCountEl.textContent !== '1') { - return ThreadStats.fetchPage(); - } - }, - update: function() { - var fileCountEl, ipCountEl, postCountEl, ref, thread; - thread = ThreadStats.thread, postCountEl = ThreadStats.postCountEl, fileCountEl = ThreadStats.fileCountEl, ipCountEl = ThreadStats.ipCountEl; - postCountEl.textContent = ThreadStats.postCount; - fileCountEl.textContent = ThreadStats.fileCount; - if (ipCountEl != null) { - ipCountEl.textContent = (ref = thread.ipCount) != null ? ref : '?'; - } - postCountEl.classList.toggle('warning', thread.postLimit && !thread.isSticky); - return fileCountEl.classList.toggle('warning', thread.fileLimit && !thread.isSticky); - }, - fetchPage: function() { - if (!ThreadStats.pageCountEl) { - return; - } - clearTimeout(ThreadStats.timeout); - if (ThreadStats.thread.isDead) { - ThreadStats.pageCountEl.textContent = 'Dead'; - $.addClass(ThreadStats.pageCountEl, 'warning'); - return; - } - ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 2 * $.MINUTE); - return $.whenModified(g.SITE.urls.threadsListJSON(ThreadStats.thread), 'ThreadStats', ThreadStats.onThreadsLoad); - }, - onThreadsLoad: function() { - var i, j, k, l, len, len1, len2, len3, len4, m, nThreads, o, page, pageNum, purgePos, ref, ref1, ref2, ref3, ref4, thread; - if (this.status === 200) { - if (ThreadStats.showPurgePos) { - purgePos = 1; - ref = this.response; - for (j = 0, len = ref.length; j < len; j++) { - page = ref[j]; - ref1 = page.threads; - for (k = 0, len1 = ref1.length; k < len1; k++) { - thread = ref1[k]; - if (thread.no < ThreadStats.thread.ID) { - purgePos++; - } - } - } - ThreadStats.pageCountEl.textContent = purgePos; - return ThreadStats.pageCountEl.classList.toggle('warning', purgePos === 1); - } else { - i = nThreads = 0; - ref2 = this.response; - for (l = 0, len2 = ref2.length; l < len2; l++) { - page = ref2[l]; - nThreads += page.threads.length; - } - ref3 = this.response; - for (pageNum = m = 0, len3 = ref3.length; m < len3; pageNum = ++m) { - page = ref3[pageNum]; - ref4 = page.threads; - for (o = 0, len4 = ref4.length; o < len4; o++) { - thread = ref4[o]; - if (thread.no === ThreadStats.thread.ID) { - ThreadStats.pageCountEl.textContent = pageNum + 1; - ThreadStats.pageCountEl.classList.toggle('warning', i >= nThreads - this.response[0].threads.length); - ThreadStats.lastPageUpdate = new Date(thread.last_modified * $.SECOND); - ThreadStats.retry(); - return; - } - i++; - } - } - } - } else if (this.status === 304) { - return ThreadStats.retry(); - } - }, - retry: function() { - if (!(ThreadStats.showPage && ThreadStats.pageCountEl.textContent !== '1' && !g.SITE.threadModTimeIgnoresSage && ThreadStats.thread.posts.get(ThreadStats.thread.lastPost).info.date > ThreadStats.lastPageUpdate)) { - return; - } - clearTimeout(ThreadStats.timeout); - return ThreadStats.timeout = setTimeout(ThreadStats.fetchPage, 5 * $.SECOND); - } - }; - - return ThreadStats; - -}).call(this); - -ThreadUpdater = (function() { - var ThreadUpdater, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - ThreadUpdater = { - init: function() { - var conf, el, input, name, ref, sc, subEntries, updateLink; - if (g.VIEW !== 'thread' || !Conf['Thread Updater']) { - return; - } - this.enabled = true; - this.audio = $.el('audio'); - if ($.engine !== 'gecko') { - this.audio.src = this.beep; - } - if (Conf['Updater and Stats in Header']) { - this.dialog = sc = $.el('span', { - id: 'updater' - }); - $.extend(sc, {innerHTML: ""}); - Header.addShortcut('updater', sc, 100); - } else { - this.dialog = sc = UI.dialog('updater', {innerHTML: "
      "}); - $.addClass(doc, 'float'); - $.ready(function() { - return $.add(d.body, sc); - }); - } - this.checkPostCount = 0; - this.timer = $('#update-timer', sc); - this.status = $('#update-status', sc); - $.on(this.timer, 'click', this.update); - $.on(this.status, 'click', this.update); - updateLink = $.el('span', { - className: 'brackets-wrap updatelink' - }); - $.extend(updateLink, {innerHTML: "Update"}); - Main.ready(function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - return $.add(navLinksBot, [$.tn(' '), updateLink]); - } - }); - $.on(updateLink.firstElementChild, 'click', this.update); - subEntries = []; - ref = Config.updater.checkbox; - for (name in ref) { - conf = ref[name]; - el = UI.checkbox(name, name); - el.title = conf[1]; - input = el.firstElementChild; - $.on(input, 'change', $.cb.checked); - if (input.name === 'Scroll BG') { - $.on(input, 'change', this.cb.scrollBG); - this.cb.scrollBG(); - } else if (input.name === 'Auto Update') { - $.on(input, 'change', this.setInterval); - } - subEntries.push({ - el: el - }); - } - this.settings = $.el('span', {innerHTML: "Interval"}); - $.on(this.settings, 'click', this.intervalShortcut); - subEntries.push({ - el: this.settings - }); - Header.menu.addEntry(this.entry = { - el: $.el('span', { - textContent: 'Updater' - }), - order: 110, - subEntries: subEntries - }); - return Callbacks.Thread.push({ - name: 'Thread Updater', - cb: this.node - }); - }, - node: function() { - ThreadUpdater.thread = this; - ThreadUpdater.root = this.nodes.root; - ThreadUpdater.outdateCount = 0; - ThreadUpdater.postIDs = []; - ThreadUpdater.fileIDs = []; - this.posts.forEach(function(post) { - ThreadUpdater.postIDs.push(post.ID); - if (post.file) { - return ThreadUpdater.fileIDs.push(post.ID); - } - }); - ThreadUpdater.cb.interval.call($.el('input', { - value: Conf['Interval'] - })); - $.on(d, 'QRPostSuccessful', ThreadUpdater.cb.checkpost); - $.on(d, 'visibilitychange', ThreadUpdater.cb.visibility); - return ThreadUpdater.setInterval(); - }, - - /* - http://freesound.org/people/pierrecartoons1979/sounds/90112/ - cc-by-nc-3.0 - */ - beep: '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', - playBeep: function() { - var audio; - audio = ThreadUpdater.audio; - audio.src || (audio.src = ThreadUpdater.beep); - if (audio.paused) { - return audio.play(); - } else { - return $.one(audio, 'ended', ThreadUpdater.playBeep); - } - }, - cb: { - checkpost: function(e) { - if (e.detail.threadID !== ThreadUpdater.thread.ID) { - return; - } - ThreadUpdater.postID = e.detail.postID; - ThreadUpdater.checkPostCount = 0; - ThreadUpdater.outdateCount = 0; - return ThreadUpdater.setInterval(); - }, - visibility: function() { - if (d.hidden) { - return; - } - ThreadUpdater.outdateCount = 0; - if (ThreadUpdater.seconds > ThreadUpdater.interval) { - return ThreadUpdater.setInterval(); - } - }, - scrollBG: function() { - return ThreadUpdater.scrollBG = Conf['Scroll BG'] ? function() { - return true; - } : function() { - return !d.hidden; - }; - }, - interval: function(e) { - var val; - val = parseInt(this.value, 10); - if (val < 1) { - val = 1; - } - ThreadUpdater.interval = this.value = val; - if (e) { - return $.cb.value.call(this); - } - }, - load: function() { - if (this !== ThreadUpdater.req) { - return; - } - switch (this.status) { - case 200: - ThreadUpdater.parse(this); - if (ThreadUpdater.thread.isArchived) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.setInterval(); - } - break; - case 404: - return $.ajax(g.SITE.urls.catalogJSON({ - boardID: ThreadUpdater.thread.board.ID - }), { - onloadend: function() { - var confirmed, i, k, len, len1, page, ref, ref1, thread; - if (this.status === 200) { - confirmed = true; - ref = this.response; - for (i = 0, len = ref.length; i < len; i++) { - page = ref[i]; - ref1 = page.threads; - for (k = 0, len1 = ref1.length; k < len1; k++) { - thread = ref1[k]; - if (thread.no === ThreadUpdater.thread.ID) { - confirmed = false; - break; - } - } - } - } else { - confirmed = false; - } - if (confirmed) { - return ThreadUpdater.kill(); - } else { - return ThreadUpdater.error(this); - } - } - }); - default: - return ThreadUpdater.error(this); - } - } - }, - kill: function() { - ThreadUpdater.thread.kill(); - ThreadUpdater.setInterval(); - return $.event('ThreadUpdate', { - 404: true, - threadID: ThreadUpdater.thread.fullID - }); - }, - error: function(req) { - if (req.status === 304) { - ThreadUpdater.set('status', ''); - } - ThreadUpdater.setInterval(); - if (!req.status) { - return ThreadUpdater.set('status', 'Connection Error', 'warning'); - } else if (req.status !== 304) { - return ThreadUpdater.set('status', req.statusText + " (" + req.status + ")", 'warning'); - } - }, - setInterval: function() { - var cur, interval, j, limit; - clearTimeout(ThreadUpdater.timeoutID); - if (ThreadUpdater.thread.isDead) { - ThreadUpdater.set('status', (ThreadUpdater.thread.isArchived ? 'Archived' : '404'), 'warning'); - ThreadUpdater.set('timer', ''); - return; - } - if (ThreadUpdater.postID && ThreadUpdater.checkPostCount < 5) { - ThreadUpdater.set('timer', '...', 'loading'); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.update, ++ThreadUpdater.checkPostCount * $.SECOND); - return; - } - if (!Conf['Auto Update']) { - ThreadUpdater.set('timer', 'Update'); - return; - } - interval = ThreadUpdater.interval; - if (Conf['Optional Increase']) { - limit = d.hidden ? 10 : 5; - j = Math.min(ThreadUpdater.outdateCount, limit); - cur = (Math.floor(interval * 0.1) || 1) * j * j; - ThreadUpdater.seconds = $.minmax(cur, interval, 300); - } else { - ThreadUpdater.seconds = interval; - } - return ThreadUpdater.timeout(); - }, - intervalShortcut: function() { - var settings; - Settings.open('Advanced'); - settings = $.id('fourchanx-settings'); - return $('input[name=Interval]', settings).focus(); - }, - set: function(name, text, klass) { - var el, node; - el = ThreadUpdater[name]; - if (node = el.firstChild) { - node.data = text; - } else { - el.textContent = text; - } - return el.className = klass != null ? klass : (text === '' ? 'empty' : ''); - }, - timeout: function() { - if (ThreadUpdater.seconds) { - ThreadUpdater.set('timer', ThreadUpdater.seconds); - ThreadUpdater.timeoutID = setTimeout(ThreadUpdater.timeout, 1000); - } else { - ThreadUpdater.outdateCount++; - ThreadUpdater.update(); - } - return ThreadUpdater.seconds--; - }, - update: function() { - var oldReq; - clearTimeout(ThreadUpdater.timeoutID); - ThreadUpdater.set('timer', '...', 'loading'); - if ((oldReq = ThreadUpdater.req)) { - delete ThreadUpdater.req; - oldReq.abort(); - } - return ThreadUpdater.req = $.whenModified(g.SITE.urls.threadJSON({ - boardID: ThreadUpdater.thread.board.ID, - threadID: ThreadUpdater.thread.ID - }), 'ThreadUpdater', ThreadUpdater.cb.load, { - timeout: $.MINUTE - }); - }, - updateThreadStatus: function(type, status) { - var change, hasChanged; - if (!(hasChanged = ThreadUpdater.thread["is" + type] !== status)) { - return; - } - ThreadUpdater.thread.setStatus(type, status); - if (type === 'Closed' && ThreadUpdater.thread.isArchived) { - return; - } - change = type === 'Sticky' ? status ? 'now a sticky' : 'not a sticky anymore' : status ? 'now closed' : 'not closed anymore'; - return new Notice('info', "The thread is " + change + ".", 30); - }, - parse: function(req) { - var ID, OP, board, deletedFiles, deletedPosts, files, firstPost, i, index, ipCountEl, k, l, lastPost, len, len1, len2, len3, m, newPosts, node, post, postObject, postObjects, posts, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, scroll, thread, unreadCount, unreadQYCount; - postObjects = req.response.posts; - OP = postObjects[0]; - thread = ThreadUpdater.thread; - board = thread.board; - ref = ThreadUpdater.postIDs, lastPost = ref[ref.length - 1]; - if (postObjects[postObjects.length - 1].no < lastPost && new Date(req.getResponseHeader('Last-Modified')) - thread.posts.get(lastPost).info.date < 30 * $.SECOND) { - return; - } - g.SITE.Build.spoilerRange[board] = OP.custom_spoiler; - thread.setStatus('Archived', !!OP.archived); - ThreadUpdater.updateThreadStatus('Sticky', !!OP.sticky); - ThreadUpdater.updateThreadStatus('Closed', !!OP.closed); - thread.postLimit = !!OP.bumplimit; - thread.fileLimit = !!OP.imagelimit; - if (OP.unique_ips != null) { - thread.ipCount = OP.unique_ips; - } - posts = []; - index = []; - files = []; - newPosts = []; - for (i = 0, len = postObjects.length; i < len; i++) { - postObject = postObjects[i]; - ID = postObject.no; - index.push(ID); - if (postObject.fsize) { - files.push(ID); - } - if (ID <= lastPost) { - continue; - } - if ((post = thread.posts.get(ID)) && !post.isFetchedQuote) { - post.resurrect(); - continue; - } - newPosts.push(board + "." + ID); - node = g.SITE.Build.postFromObject(postObject, board.ID); - posts.push(new Post(node, thread, board)); - if (ThreadUpdater.postID === ID) { - delete ThreadUpdater.postID; - } - } - deletedPosts = []; - ref1 = ThreadUpdater.postIDs; - for (k = 0, len1 = ref1.length; k < len1; k++) { - ID = ref1[k]; - if (!(indexOf.call(index, ID) < 0)) { - continue; - } - thread.posts.get(ID).kill(); - deletedPosts.push(board + "." + ID); - } - ThreadUpdater.postIDs = index; - deletedFiles = []; - ref2 = ThreadUpdater.fileIDs; - for (l = 0, len2 = ref2.length; l < len2; l++) { - ID = ref2[l]; - if (!(!(indexOf.call(files, ID) >= 0 || (ref3 = board + "." + ID, indexOf.call(deletedPosts, ref3) >= 0)))) { - continue; - } - thread.posts.get(ID).kill(true); - deletedFiles.push(board + "." + ID); - } - ThreadUpdater.fileIDs = files; - if (!posts.length) { - ThreadUpdater.set('status', ''); - } else { - ThreadUpdater.set('status', "+" + posts.length, 'new'); - ThreadUpdater.outdateCount = 0; - unreadCount = (ref4 = Unread.posts) != null ? ref4.size : void 0; - unreadQYCount = (ref5 = Unread.postsQuotingYou) != null ? ref5.size : void 0; - Main.callbackNodes('Post', posts); - if (d.hidden || !d.hasFocus()) { - if (Conf['Beep Quoting You'] && ((ref6 = Unread.postsQuotingYou) != null ? ref6.size : void 0) > unreadQYCount) { - ThreadUpdater.playBeep(); - if (Conf['Beep']) { - ThreadUpdater.playBeep(); - } - } else if (Conf['Beep'] && ((ref7 = Unread.posts) != null ? ref7.size : void 0) > 0 && unreadCount === 0) { - ThreadUpdater.playBeep(); - } - } - scroll = Conf['Auto Scroll'] && ThreadUpdater.scrollBG() && ThreadUpdater.root.getBoundingClientRect().bottom - doc.clientHeight < 25; - firstPost = null; - for (m = 0, len3 = posts.length; m < len3; m++) { - post = posts[m]; - if (!QuoteThreading.insert(post)) { - firstPost || (firstPost = post.nodes.root); - $.add(ThreadUpdater.root, post.nodes.root); - } - } - $.event('PostsInserted', null, ThreadUpdater.root); - if (scroll) { - if (Conf['Bottom Scroll']) { - window.scrollTo(0, d.body.clientHeight); - } else { - if (firstPost) { - Header.scrollTo(firstPost); - } - } - } - } - if ((OP.unique_ips != null) && (ipCountEl = $.id('unique-ips'))) { - ipCountEl.textContent = OP.unique_ips; - ipCountEl.previousSibling.textContent = ipCountEl.previousSibling.textContent.replace(/\b(?:is|are)\b/, OP.unique_ips === 1 ? 'is' : 'are'); - ipCountEl.nextSibling.textContent = ipCountEl.nextSibling.textContent.replace(/\bposters?\b/, OP.unique_ips === 1 ? 'poster' : 'posters'); - } - return $.event('ThreadUpdate', { - 404: false, - threadID: thread.fullID, - newPosts: newPosts, - deletedPosts: deletedPosts, - deletedFiles: deletedFiles, - postCount: OP.replies + 1, - fileCount: OP.images + !!OP.fsize, - ipCount: OP.unique_ips - }); - } - }; - - return ThreadUpdater; - -}).call(this); - -ThreadWatcher = (function() { - var ThreadWatcher, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - ThreadWatcher = { - init: function() { - var ref, sc; - if (!(this.enabled = Conf['Thread Watcher'])) { - return; - } - this.shortcut = sc = $.el('a', { - id: 'watcher-link', - textContent: 'Watcher', - title: 'Thread Watcher', - href: 'javascript:;', - className: 'fa fa-eye' - }); - this.db = new DataBoard('watchedThreads', this.refresh, true); - this.dbLM = new DataBoard('watcherLastModified', null, true); - this.dialog = UI.dialog('thread-watcher', {innerHTML: "
      Thread Watcher ×
      "}); - this.status = $('#watcher-status', this.dialog); - this.list = this.dialog.lastElementChild; - this.refreshButton = $('.refresh', this.dialog); - this.closeButton = $('.move > .close', this.dialog); - this.unreaddb = Unread.db || UnreadIndex.db || new DataBoard('lastReadPosts'); - this.unreadEnabled = Conf['Remember Last Read Post']; - $.on(d, 'QRPostSuccessful', this.cb.post); - $.on(sc, 'click', this.toggleWatcher); - $.on(this.refreshButton, 'click', this.buttonFetchAll); - $.on(this.closeButton, 'click', this.toggleWatcher); - this.menu.addHeaderMenuEntry(); - $.onExists(doc, 'body', this.addDialog); - switch (g.VIEW) { - case 'index': - $.on(d, 'IndexUpdate', this.cb.onIndexUpdate); - break; - case 'thread': - $.on(d, 'ThreadUpdate', this.cb.onThreadRefresh); - } - if (Conf['Fixed Thread Watcher']) { - $.addClass(doc, 'fixed-watcher'); - } - if (!Conf['Persistent Thread Watcher']) { - $.addClass(ThreadWatcher.shortcut, 'disabled'); - this.dialog.hidden = true; - } - Header.addShortcut('watcher', sc, 510); - ThreadWatcher.initLastModified(); - ThreadWatcher.fetchAuto(); - $.on(window, 'visibilitychange focus', function() { - return $.queueTask(ThreadWatcher.fetchAuto); - }); - if (Conf['Menu'] && Index.enabled) { - Menu.menu.addEntry({ - el: $.el('a', { - href: 'javascript:;', - className: 'has-shortcut-text' - }, {innerHTML: "Alt+click"}), - order: 6, - open: function(arg) { - var thread; - thread = arg.thread; - if (Conf['Index Mode'] !== 'catalog') { - return false; - } - this.el.firstElementChild.textContent = ThreadWatcher.isWatched(thread) ? 'Unwatch' : 'Watch'; - if (this.cb) { - $.off(this.el, 'click', this.cb); - } - this.cb = function() { - $.event('CloseMenu'); - return ThreadWatcher.toggle(thread); - }; - $.on(this.el, 'click', this.cb); - return true; - } - }); - } - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - Callbacks.Post.push({ - name: 'Thread Watcher', - cb: this.node - }); - return Callbacks.CatalogThread.push({ - name: 'Thread Watcher', - cb: this.catalogNode - }); - }, - isWatched: function(thread) { - var ref; - return !!((ref = ThreadWatcher.db) != null ? ref.get({ - boardID: thread.board.ID, - threadID: thread.ID - }) : void 0); - }, - isWatchedRaw: function(boardID, threadID) { - var ref; - return !!((ref = ThreadWatcher.db) != null ? ref.get({ - boardID: boardID, - threadID: threadID - }) : void 0); - }, - setToggler: function(toggler, isWatched) { - toggler.classList.toggle('watched', isWatched); - return toggler.title = (isWatched ? 'Unwatch' : 'Watch') + " Thread"; - }, - node: function() { - var boardID, data, siteID, threadID, toggler; - if (this.isReply) { - return; - } - if (this.isClone) { - toggler = $('.watch-thread-link', this.nodes.info); - } else { - toggler = $.el('a', { - href: 'javascript:;', - className: 'watch-thread-link' - }); - $.before($('input', this.nodes.info), toggler); - } - siteID = g.SITE.ID; - boardID = this.board.ID; - threadID = this.thread.ID; - data = ThreadWatcher.db.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }); - ThreadWatcher.setToggler(toggler, !!data); - $.on(toggler, 'click', ThreadWatcher.cb.toggle); - if (data && (data.excerpt == null)) { - return $.queueTask((function(_this) { - return function() { - return ThreadWatcher.update(siteID, boardID, threadID, { - excerpt: Get.threadExcerpt(_this.thread) - }); - }; - })(this)); - } - }, - catalogNode: function() { - if (ThreadWatcher.isWatched(this.thread)) { - $.addClass(this.nodes.root, 'watched'); - } - return $.on(this.nodes.root, 'mousedown click', (function(_this) { - return function(e) { - if (!(e.button === 0 && e.altKey)) { - return; - } - if (e.type === 'click') { - ThreadWatcher.toggle(_this.thread); - } - return e.preventDefault(); - }; - })(this)); - }, - addDialog: function() { - if (!Main.isThisPageLegit()) { - return; - } - ThreadWatcher.build(); - return $.prepend(d.body, ThreadWatcher.dialog); - }, - toggleWatcher: function() { - $.toggleClass(ThreadWatcher.shortcut, 'disabled'); - return ThreadWatcher.dialog.hidden = !ThreadWatcher.dialog.hidden; - }, - cb: { - openAll: function() { - var a, j, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('a.watcher-link', ThreadWatcher.list); - for (j = 0, len1 = ref.length; j < len1; j++) { - a = ref[j]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - openUnread: function() { - var a, j, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('.replies-unread > a.watcher-link', ThreadWatcher.list); - for (j = 0, len1 = ref.length; j < len1; j++) { - a = ref[j]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - openDeads: function() { - var a, j, len1, ref; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = $$('.dead-thread > a.watcher-link', ThreadWatcher.list); - for (j = 0, len1 = ref.length; j < len1; j++) { - a = ref[j]; - $.open(a.href); - } - return $.event('CloseMenu'); - }, - pruneDeads: function() { - var boardID, data, j, len1, ref, ref1, siteID, threadID; - if ($.hasClass(this, 'disabled')) { - return; - } - ref = ThreadWatcher.getAll(); - for (j = 0, len1 = ref.length; j < len1; j++) { - ref1 = ref[j], siteID = ref1.siteID, boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; - if (data.isDead) { - ThreadWatcher.db["delete"]({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }); - } - } - ThreadWatcher.refresh(); - return $.event('CloseMenu'); - }, - dismiss: function() { - var boardID, data, j, len1, ref, ref1, siteID, threadID; - ref = ThreadWatcher.getAll(); - for (j = 0, len1 = ref.length; j < len1; j++) { - ref1 = ref[j], siteID = ref1.siteID, boardID = ref1.boardID, threadID = ref1.threadID, data = ref1.data; - if (data.quotingYou) { - ThreadWatcher.update(siteID, boardID, threadID, { - dismiss: data.quotingYou || 0 - }); - } - } - return $.event('CloseMenu'); - }, - toggle: function() { - var thread; - thread = Get.postFromNode(this).thread; - return ThreadWatcher.toggle(thread); - }, - rm: function() { - var boardID, ref, siteID, threadID; - siteID = this.parentNode.dataset.siteID; - ref = this.parentNode.dataset.fullID.split('.'), boardID = ref[0], threadID = ref[1]; - return ThreadWatcher.rm(siteID, boardID, +threadID); - }, - post: function(e) { - var boardID, cb, postID, ref, threadID; - ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - cb = PostRedirect.delay(); - if (postID === threadID) { - if (Conf['Auto Watch']) { - return ThreadWatcher.addRaw(boardID, threadID, {}, cb); - } - } else if (Conf['Auto Watch Reply']) { - return ThreadWatcher.add(g.threads.get(boardID + '.' + threadID) || new Thread(threadID, g.boards[boardID] || new Board(boardID)), cb); - } - }, - onIndexUpdate: function(e) { - var boardID, data, db, nKilled, ref, ref1, siteID, threadID; - db = ThreadWatcher.db; - siteID = g.SITE.ID; - boardID = g.BOARD.ID; - nKilled = 0; - ref = db.data[siteID].boards[boardID]; - for (threadID in ref) { - data = ref[threadID]; - if (!(!(data != null ? data.isDead : void 0) && (ref1 = boardID + "." + threadID, indexOf.call(e.detail.threads, ref1) < 0))) { - continue; - } - if (!e.detail.threads.some(function(fullID) { - return +fullID.split('.')[1] > threadID; - })) { - continue; - } - if (Conf['Auto Prune'] || !(data && typeof data === 'object')) { - db["delete"]({ - boardID: boardID, - threadID: threadID - }); - nKilled++; - } else { - ThreadWatcher.fetchStatus({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - data: data - }); - } - } - if (nKilled) { - return ThreadWatcher.refresh(); - } - }, - onThreadRefresh: function(e) { - var thread; - thread = g.threads.get(e.detail.threadID); - if (!(e.detail[404] && ThreadWatcher.isWatched(thread))) { - return; - } - return ThreadWatcher.add(thread); - } - }, - requests: [], - fetched: 0, - fetch: function(url, arg, args, cb) { - var ajax, force, onloadend, ref, req, siteID; - siteID = arg.siteID, force = arg.force; - if (ThreadWatcher.requests.length === 0) { - ThreadWatcher.status.textContent = '...'; - $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); - } - onloadend = function() { - if (this.finished) { - return; - } - this.finished = true; - ThreadWatcher.fetched++; - if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { - ThreadWatcher.clearRequests(); - } else { - ThreadWatcher.status.textContent = (Math.round(ThreadWatcher.fetched / ThreadWatcher.requests.length * 100)) + "%"; - } - return cb.apply(this, args); - }; - ajax = siteID === g.SITE.ID ? $.ajax : CrossOrigin.ajax; - if (force) { - if ((ref = $.lastModified.ThreadWatcher) != null) { - delete ref[url]; - } - } - req = $.whenModified(url, 'ThreadWatcher', onloadend, { - timeout: $.MINUTE, - ajax: ajax - }); - return ThreadWatcher.requests.push(req); - }, - clearRequests: function() { - ThreadWatcher.requests = []; - ThreadWatcher.fetched = 0; - ThreadWatcher.status.textContent = ''; - return $.rmClass(ThreadWatcher.refreshButton, 'fa-spin'); - }, - abort: function() { - var j, len1, ref, req; - delete ThreadWatcher.syncing; - ref = ThreadWatcher.requests; - for (j = 0, len1 = ref.length; j < len1; j++) { - req = ref[j]; - if (!(!req.finished)) { - continue; - } - req.finished = true; - req.abort(); - } - return ThreadWatcher.clearRequests(); - }, - initLastModified: function() { - var base, boardID, boards, data, date, lm, ref, ref1, siteID, url; - lm = ((base = $.lastModified)['ThreadWatcher'] || (base['ThreadWatcher'] = $.dict())); - ref = ThreadWatcher.dbLM.data; - for (siteID in ref) { - boards = ref[siteID]; - ref1 = boards.boards; - for (boardID in ref1) { - data = ref1[boardID]; - if (ThreadWatcher.db.get({ - siteID: siteID, - boardID: boardID - })) { - for (url in data) { - date = data[url]; - lm[url] = date; - } - } else { - ThreadWatcher.dbLM["delete"]({ - siteID: siteID, - boardID: boardID - }); - } - } - } - }, - fetchAuto: function() { - var db, interval, now, ref; - clearTimeout(ThreadWatcher.timeout); - if (!Conf['Auto Update Thread Watcher']) { - return; - } - db = ThreadWatcher.db; - interval = Conf['Show Page'] || (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) ? 5 * $.MINUTE : 2 * $.HOUR; - now = Date.now(); - if (!((now - interval < (ref = db.data.lastChecked || 0) && ref <= now) || d.hidden || !d.hasFocus())) { - ThreadWatcher.fetchAllStatus(interval); - } - return ThreadWatcher.timeout = setTimeout(ThreadWatcher.fetchAuto, interval); - }, - buttonFetchAll: function() { - if (ThreadWatcher.syncing || ThreadWatcher.requests.length) { - return ThreadWatcher.abort(); - } else { - return ThreadWatcher.fetchAllStatus(); - } - }, - fetchAllStatus: function(interval) { - var dbi, dbs, j, len1, n, results; - if (interval == null) { - interval = 0; - } - ThreadWatcher.status.textContent = '...'; - $.addClass(ThreadWatcher.refreshButton, 'fa-spin'); - ThreadWatcher.syncing = true; - dbs = [ThreadWatcher.db, ThreadWatcher.unreaddb, QuoteYou.db].filter(function(x) { - return x; - }); - n = 0; - results = []; - for (j = 0, len1 = dbs.length; j < len1; j++) { - dbi = dbs[j]; - results.push(dbi.forceSync(function() { - var board, boards, db, deep, k, len2, now, ref, ref1; - if ((++n) === dbs.length) { - if (!ThreadWatcher.syncing) { - return; - } - delete ThreadWatcher.syncing; - if (!((0 <= (ref = Date.now() - (ThreadWatcher.db.data.lastChecked || 0)) && ref < interval))) { - db = ThreadWatcher.db; - now = Date.now(); - deep = !((now - 2 * $.HOUR < (ref1 = db.data.lastChecked2 || 0) && ref1 <= now)); - boards = ThreadWatcher.getAll(true); - for (k = 0, len2 = boards.length; k < len2; k++) { - board = boards[k]; - ThreadWatcher.fetchBoard(board, deep); - } - db.setLastChecked(); - if (deep) { - db.setLastChecked('lastChecked2'); - } - } - if (ThreadWatcher.fetched === ThreadWatcher.requests.length) { - return ThreadWatcher.clearRequests(); - } - } - })); - } - return results; - }, - fetchBoard: function(board, deep) { - var base, boardID, data, force, j, len1, ref, site, siteID, thread, url, urlF; - if (!board.some(function(thread) { - return !thread.data.isDead; - })) { - return; - } - force = false; - for (j = 0, len1 = board.length; j < len1; j++) { - thread = board[j]; - data = thread.data; - if (!data.isDead && data.last !== -1) { - if (Conf['Show Page'] && (data.page == null)) { - force = true; - } - if (data.modified == null) { - force = thread.force = true; - } - } - } - ref = board[0], siteID = ref.siteID, boardID = ref.boardID; - site = g.sites[siteID]; - if (!site) { - return; - } - urlF = deep && site.threadModTimeIgnoresSage ? 'catalogJSON' : 'threadsListJSON'; - url = typeof (base = site.urls)[urlF] === "function" ? base[urlF]({ - siteID: siteID, - boardID: boardID - }) : void 0; - if (!url) { - return; - } - return ThreadWatcher.fetch(url, { - siteID: siteID, - force: force - }, [board, url], ThreadWatcher.parseBoard); - }, - parseBoard: function(board, url) { - var base, boardID, data, i, index, item, j, k, l, lastPage, len1, len2, len3, len4, lmDate, m, modified, nThreads, oldest, page, pageLength, ref, ref1, ref2, ref3, ref4, replies, siteID, thread, threadID, threads; - if (this.status !== 200) { - return; - } - ref = board[0], siteID = ref.siteID, boardID = ref.boardID; - lmDate = this.getResponseHeader('Last-Modified'); - ThreadWatcher.dbLM.extend({ - siteID: siteID, - boardID: boardID, - val: $.item(url, lmDate) - }); - threads = $.dict(); - pageLength = 0; - nThreads = 0; - oldest = null; - try { - pageLength = ((ref1 = this.response[0]) != null ? ref1.threads.length : void 0) || 0; - ref2 = this.response; - for (i = j = 0, len1 = ref2.length; j < len1; i = ++j) { - page = ref2[i]; - ref3 = page.threads; - for (k = 0, len2 = ref3.length; k < len2; k++) { - item = ref3[k]; - threads[item.no] = { - page: i + 1, - index: nThreads, - modified: item.last_modified, - replies: item.replies - }; - nThreads++; - if ((oldest == null) || item.no < oldest) { - oldest = item.no; - } - } - } - } catch (error) { - for (l = 0, len3 = board.length; l < len3; l++) { - thread = board[l]; - ThreadWatcher.fetchStatus(thread); - } - } - for (m = 0, len4 = board.length; m < len4; m++) { - thread = board[m]; - threadID = thread.threadID, data = thread.data; - if (threads[threadID]) { - ref4 = threads[threadID], page = ref4.page, index = ref4.index, modified = ref4.modified, replies = ref4.replies; - if (Conf['Show Page']) { - lastPage = (typeof (base = g.sites[siteID]).isPrunedByAge === "function" ? base.isPrunedByAge({ - siteID: siteID, - boardID: boardID - }) : void 0) ? threadID === oldest : index >= nThreads - pageLength; - ThreadWatcher.update(siteID, boardID, threadID, { - page: page, - lastPage: lastPage - }); - } - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - if (modified !== data.modified || ((replies != null) && replies !== data.replies)) { - (thread.newData || (thread.newData = {})).modified = modified; - ThreadWatcher.fetchStatus(thread); - } - } - } else { - ThreadWatcher.fetchStatus(thread); - } - } - }, - fetchStatus: function(thread) { - var base, boardID, data, force, ref, siteID, threadID, url; - siteID = thread.siteID, boardID = thread.boardID, threadID = thread.threadID, data = thread.data, force = thread.force; - url = (ref = g.sites[siteID]) != null ? typeof (base = ref.urls).threadJSON === "function" ? base.threadJSON({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }) : void 0 : void 0; - if (!url) { - return; - } - if (data.isDead && !force) { - return; - } - if (data.last === -1) { - return; - } - return ThreadWatcher.fetch(url, { - siteID: siteID, - force: force - }, [thread], ThreadWatcher.parseStatus); - }, - parseStatus: function(thread, isArchiveURL) { - var archiveURL, base, boardID, data, force, isArchived, isDead, j, last, lastReadPost, len1, match, newData, postObj, quotesYou, quotingYou, ref, ref1, ref2, ref3, regexp, replies, site, siteID, threadID, unread, youOP; - siteID = thread.siteID, boardID = thread.boardID, threadID = thread.threadID, data = thread.data, newData = thread.newData, force = thread.force; - site = g.sites[siteID]; - if (this.status === 200 && this.response) { - last = this.response.posts[this.response.posts.length - 1].no; - replies = this.response.posts.length - 1; - isDead = isArchived = !!(this.response.posts[0].archived || isArchiveURL); - if (isDead && Conf['Auto Prune']) { - ThreadWatcher.rm(siteID, boardID, threadID); - return; - } - if (last === data.last && isDead === data.isDead && isArchived === data.isArchived) { - return; - } - lastReadPost = ThreadWatcher.unreaddb.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - defaultValue: 0 - }); - unread = data.unread || 0; - quotingYou = data.quotingYou || 0; - youOP = !!((ref = QuoteYou.db) != null ? ref.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: threadID - }) : void 0); - ref1 = this.response.posts; - for (j = 0, len1 = ref1.length; j < len1; j++) { - postObj = ref1[j]; - if (!(postObj.no > (data.last || 0) && postObj.no > lastReadPost)) { - continue; - } - if ((ref2 = QuoteYou.db) != null ? ref2.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - postID: postObj.no - }) : void 0) { - continue; - } - quotesYou = false; - if (!Conf['Require OP Quote Link'] && youOP) { - quotesYou = true; - } else if (QuoteYou.db && postObj.com) { - regexp = site.regexp.quotelinkHTML; - regexp.lastIndex = 0; - while ((match = regexp.exec(postObj.com))) { - if (QuoteYou.db.get({ - siteID: siteID, - boardID: match[1] ? encodeURIComponent(match[1]) : boardID, - threadID: match[2] || threadID, - postID: match[3] || match[2] || threadID - })) { - quotesYou = true; - break; - } - } - } - if (!unread || (!quotingYou && quotesYou)) { - if (Filter.isHidden(site.Build.parseJSON(postObj, { - siteID: siteID, - boardID: boardID - }))) { - continue; - } - } - unread++; - if (quotesYou) { - quotingYou = postObj.no; - } - } - newData || (newData = {}); - $.extend(newData, { - last: last, - replies: replies, - isDead: isDead, - isArchived: isArchived, - unread: unread, - quotingYou: quotingYou - }); - return ThreadWatcher.update(siteID, boardID, threadID, newData); - } else if (this.status === 404) { - archiveURL = (ref3 = g.sites[siteID]) != null ? typeof (base = ref3.urls).archivedThreadJSON === "function" ? base.archivedThreadJSON({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }) : void 0 : void 0; - if (!isArchiveURL && archiveURL) { - return ThreadWatcher.fetch(archiveURL, { - siteID: siteID, - force: force - }, [thread, true], ThreadWatcher.parseStatus); - } else if (site.mayLackJSON && (data.last == null)) { - return ThreadWatcher.update(siteID, boardID, threadID, { - last: -1 - }); - } else { - return ThreadWatcher.update(siteID, boardID, threadID, { - isDead: true - }); - } - } - }, - getAll: function(groupByBoard) { - var all, boardID, boards, cont, data, ref, ref1, siteID, threadID, threads; - all = []; - ref = ThreadWatcher.db.data; - for (siteID in ref) { - boards = ref[siteID]; - ref1 = boards.boards; - for (boardID in ref1) { - threads = ref1[boardID]; - if (Conf['Current Board'] && (siteID !== g.SITE.ID || boardID !== g.BOARD.ID)) { - continue; - } - if (groupByBoard) { - all.push((cont = [])); - } - for (threadID in threads) { - data = threads[threadID]; - if (data && typeof data === 'object') { - (groupByBoard ? cont : all).push({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - data: data - }); - } - } - } - } - return all; - }, - makeLine: function(siteID, boardID, threadID, data) { - var count, div, excerpt, fullID, isArchived, link, page, ref, title, x; - x = $.el('a', { - className: 'fa fa-times', - href: 'javascript:;' - }); - $.on(x, 'click', ThreadWatcher.cb.rm); - excerpt = data.excerpt, isArchived = data.isArchived; - excerpt || (excerpt = "/" + boardID + "/ - No." + threadID); - if (Conf['Show Site Prefix']) { - excerpt = ThreadWatcher.prefixes[siteID] + excerpt; - } - link = $.el('a', { - href: ((ref = g.sites[siteID]) != null ? ref.urls.thread({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }, isArchived) : void 0) || '', - title: excerpt, - className: 'watcher-link' - }); - if (Conf['Show Page'] && (data.page != null)) { - page = $.el('span', { - textContent: "[" + data.page + "]", - className: 'watcher-page' - }); - $.add(link, page); - } - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count'] && (data.unread != null)) { - count = $.el('span', { - textContent: "(" + data.unread + ")", - className: 'watcher-unread' - }); - $.add(link, count); - } - title = $.el('span', { - textContent: excerpt, - className: 'watcher-title' - }); - $.add(link, title); - div = $.el('div'); - fullID = boardID + "." + threadID; - div.dataset.fullID = fullID; - div.dataset.siteID = siteID; - if (g.VIEW === 'thread' && fullID === (g.BOARD + "." + g.THREADID)) { - $.addClass(div, 'current'); - } - if (data.isDead) { - $.addClass(div, 'dead-thread'); - } - if (Conf['Show Page']) { - if (data.lastPage) { - $.addClass(div, 'last-page'); - } - if (data.page != null) { - div.dataset.page = data.page; - } - } - if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - if (data.unread === 0) { - $.addClass(div, 'replies-read'); - } - if (data.unread) { - $.addClass(div, 'replies-unread'); - } - if ((data.quotingYou || 0) > (data.dismiss || 0)) { - $.addClass(div, 'replies-quoting-you'); - } - } - $.add(div, [x, $.tn(' '), link]); - return div; - }, - setPrefixes: function(threads) { - var conflicts, conflicts2, j, k, len, len1, len2, prefix, prefixes, siteID, siteID2; - prefixes = $.dict(); - for (j = 0, len1 = threads.length; j < len1; j++) { - siteID = threads[j].siteID; - if (siteID in prefixes) { - continue; - } - len = 0; - prefix = ''; - conflicts = Object.keys(prefixes); - while (conflicts.length > 0) { - len++; - prefix = siteID.slice(0, len); - conflicts2 = []; - for (k = 0, len2 = conflicts.length; k < len2; k++) { - siteID2 = conflicts[k]; - if (siteID2.slice(0, len) === prefix) { - conflicts2.push(siteID2); - } else if (prefixes[siteID2].length < len) { - prefixes[siteID2] = siteID2.slice(0, len); - } - } - conflicts = conflicts2; - } - prefixes[siteID] = prefix; - } - return ThreadWatcher.prefixes = prefixes; - }, - build: function() { - var boardID, data, j, len1, list, nodes, ref, siteID, thread, threadID, threads; - nodes = []; - threads = ThreadWatcher.getAll(); - ThreadWatcher.setPrefixes(threads); - for (j = 0, len1 = threads.length; j < len1; j++) { - ref = threads[j], siteID = ref.siteID, boardID = ref.boardID, threadID = ref.threadID, data = ref.data; - if ((data.excerpt == null) && siteID === g.SITE.ID && (thread = g.threads.get(boardID + "." + threadID)) && thread.OP) { - ThreadWatcher.db.extend({ - boardID: boardID, - threadID: threadID, - val: { - excerpt: Get.threadExcerpt(thread) - } - }); - } - nodes.push(ThreadWatcher.makeLine(siteID, boardID, threadID, data)); - } - list = ThreadWatcher.list; - $.rmAll(list); - $.add(list, nodes); - return ThreadWatcher.refreshIcon(); - }, - refresh: function() { - ThreadWatcher.build(); - g.threads.forEach(function(thread) { - var isWatched, j, len1, post, ref, toggler; - isWatched = ThreadWatcher.isWatched(thread); - if (thread.OP) { - ref = [thread.OP].concat(slice.call(thread.OP.clones)); - for (j = 0, len1 = ref.length; j < len1; j++) { - post = ref[j]; - if ((toggler = $('.watch-thread-link', post.nodes.info))) { - ThreadWatcher.setToggler(toggler, isWatched); - } - } - } - if (thread.catalogView) { - return thread.catalogView.nodes.root.classList.toggle('watched', isWatched); - } - }); - if (Conf['Pin Watched Threads']) { - return $.event('SortIndex', { - deferred: Conf['Index Mode'] !== 'catalog' - }); - } - }, - refreshIcon: function() { - var className, j, len1, ref; - ref = ['replies-unread', 'replies-quoting-you']; - for (j = 0, len1 = ref.length; j < len1; j++) { - className = ref[j]; - ThreadWatcher.shortcut.classList.toggle(className, !!$("." + className, ThreadWatcher.dialog)); - } - }, - update: function(siteID, boardID, threadID, newData) { - var data, j, key, len1, line, n, newLine, ref, ref1, val; - if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }) : void 0)) { - return; - } - if (newData.isDead && Conf['Auto Prune']) { - ThreadWatcher.rm(siteID, boardID, threadID); - return; - } - if (newData.isDead || newData.last === -1) { - ref1 = ['isArchived', 'page', 'lastPage', 'unread', 'quotingyou']; - for (j = 0, len1 = ref1.length; j < len1; j++) { - key = ref1[j]; - if (!(key in newData)) { - newData[key] = void 0; - } - } - } - if ((newData.last != null) && newData.last < data.last) { - newData.modified = void 0; - } - n = 0; - for (key in newData) { - val = newData[key]; - if (data[key] !== val) { - n++; - } - } - if (!n) { - return; - } - ThreadWatcher.db.extend({ - siteID: siteID, - boardID: boardID, - threadID: threadID, - val: newData - }); - if ((line = $("#watched-threads > [data-site-i-d='" + siteID + "'][data-full-i-d='" + boardID + "." + threadID + "']", ThreadWatcher.dialog))) { - newLine = ThreadWatcher.makeLine(siteID, boardID, threadID, data); - $.replace(line, newLine); - return ThreadWatcher.refreshIcon(); - } else { - return ThreadWatcher.refresh(); - } - }, - set404: function(boardID, threadID, cb) { - var data, ref; - if (!(data = (ref = ThreadWatcher.db) != null ? ref.get({ - boardID: boardID, - threadID: threadID - }) : void 0)) { - return cb(); - } - if (Conf['Auto Prune']) { - ThreadWatcher.db["delete"]({ - boardID: boardID, - threadID: threadID - }); - return cb(); - } - if (data.isDead && !((data.isArchived != null) || (data.page != null) || (data.lastPage != null) || (data.unread != null) || (data.quotingYou != null))) { - return cb(); - } - return ThreadWatcher.db.extend({ - boardID: boardID, - threadID: threadID, - val: { - isDead: true, - isArchived: void 0, - page: void 0, - lastPage: void 0, - unread: void 0, - quotingYou: void 0 - } - }, cb); - }, - toggle: function(thread) { - var boardID, siteID, threadID; - siteID = g.SITE.ID; - boardID = thread.board.ID; - threadID = thread.ID; - if (ThreadWatcher.db.get({ - boardID: boardID, - threadID: threadID - })) { - return ThreadWatcher.rm(siteID, boardID, threadID); - } else { - return ThreadWatcher.add(thread); - } - }, - add: function(thread, cb) { - var boardID, data, siteID, threadID; - data = {}; - siteID = g.SITE.ID; - boardID = thread.board.ID; - threadID = thread.ID; - if (thread.isDead) { - if (Conf['Auto Prune'] && ThreadWatcher.db.get({ - boardID: boardID, - threadID: threadID - })) { - ThreadWatcher.rm(siteID, boardID, threadID, cb); - return; - } - data.isDead = true; - } - if (thread.OP) { - data.excerpt = Get.threadExcerpt(thread); - } - return ThreadWatcher.addRaw(boardID, threadID, data, cb); - }, - addRaw: function(boardID, threadID, data, cb) { - var oldData, thread; - oldData = ThreadWatcher.db.get({ - boardID: boardID, - threadID: threadID, - defaultValue: $.dict() - }); - delete oldData.last; - delete oldData.modified; - $.extend(oldData, data); - ThreadWatcher.db.set({ - boardID: boardID, - threadID: threadID, - val: oldData - }, cb); - ThreadWatcher.refresh(); - thread = { - siteID: g.SITE.ID, - boardID: boardID, - threadID: threadID, - data: data, - force: true - }; - if (Conf['Show Page'] && !data.isDead) { - return ThreadWatcher.fetchBoard([thread]); - } else if (ThreadWatcher.unreadEnabled && Conf['Show Unread Count']) { - return ThreadWatcher.fetchStatus(thread); - } - }, - rm: function(siteID, boardID, threadID, cb) { - ThreadWatcher.db["delete"]({ - siteID: siteID, - boardID: boardID, - threadID: threadID - }, cb); - return ThreadWatcher.refresh(); - }, - menu: { - init: function() { - var menu; - if (!Conf['Thread Watcher']) { - return; - } - menu = this.menu = new UI.Menu('thread watcher'); - $.on($('.menu-button', ThreadWatcher.dialog), 'click', function(e) { - return menu.toggle(e, this, ThreadWatcher); - }); - return this.addMenuEntries(); - }, - addHeaderMenuEntry: function() { - var entryEl; - if (g.VIEW !== 'thread') { - return; - } - entryEl = $.el('a', { - href: 'javascript:;' - }); - Header.menu.addEntry({ - el: entryEl, - order: 60, - open: function() { - var addClass, ref, rmClass, text; - ref = !!ThreadWatcher.db.get({ - boardID: g.BOARD.ID, - threadID: g.THREADID - }) ? ['unwatch-thread', 'watch-thread', 'Unwatch thread'] : ['watch-thread', 'unwatch-thread', 'Watch thread'], addClass = ref[0], rmClass = ref[1], text = ref[2]; - $.addClass(entryEl, addClass); - $.rmClass(entryEl, rmClass); - entryEl.textContent = text; - return true; - } - }); - return $.on(entryEl, 'click', function() { - return ThreadWatcher.toggle(g.threads.get(g.BOARD + "." + g.THREADID)); - }); - }, - addMenuEntries: function() { - var cb, conf, entries, entry, j, len1, name, open, ref, ref1, text, title; - entries = []; - entries.push({ - text: 'Open all threads', - cb: ThreadWatcher.cb.openAll, - open: function() { - this.el.classList.toggle('disabled', !ThreadWatcher.list.firstElementChild); - return true; - } - }); - entries.push({ - text: 'Open unread threads', - cb: ThreadWatcher.cb.openUnread, - open: function() { - this.el.classList.toggle('disabled', !$('.replies-unread', ThreadWatcher.list)); - return true; - } - }); - entries.push({ - text: 'Open dead threads', - cb: ThreadWatcher.cb.openDeads, - open: function() { - this.el.classList.toggle('disabled', !$('.dead-thread', ThreadWatcher.list)); - return true; - } - }); - entries.push({ - text: 'Prune dead threads', - cb: ThreadWatcher.cb.pruneDeads, - open: function() { - this.el.classList.toggle('disabled', !$('.dead-thread', ThreadWatcher.list)); - return true; - } - }); - entries.push({ - text: 'Dismiss posts quoting you', - title: 'Unhighlight the thread watcher icon and threads until there are new replies quoting you.', - cb: ThreadWatcher.cb.dismiss, - open: function() { - this.el.classList.toggle('disabled', !$.hasClass(ThreadWatcher.shortcut, 'replies-quoting-you')); - return true; - } - }); - for (j = 0, len1 = entries.length; j < len1; j++) { - ref = entries[j], text = ref.text, title = ref.title, cb = ref.cb, open = ref.open; - entry = { - el: $.el('a', { - textContent: text, - href: 'javascript:;' - }) - }; - if (title) { - entry.el.title = title; - } - $.on(entry.el, 'click', cb); - entry.open = open.bind(entry); - this.menu.addEntry(entry); - } - ref1 = Config.threadWatcher; - for (name in ref1) { - conf = ref1[name]; - this.addCheckbox(name, conf[1]); - } - }, - addCheckbox: function(name, desc) { - var entry, input; - entry = { - type: 'thread watcher', - el: UI.checkbox(name, name.replace(' Thread Watcher', '')) - }; - entry.el.title = desc; - input = entry.el.firstElementChild; - if (name === 'Show Unread Count' && !ThreadWatcher.unreadEnabled) { - input.disabled = true; - $.addClass(entry.el, 'disabled'); - entry.el.title += '\n[Remember Last Read Post is disabled.]'; - } - $.on(input, 'change', $.cb.checked); - if (name === 'Current Board' || name === 'Show Page' || name === 'Show Unread Count' || name === 'Show Site Prefix') { - $.on(input, 'change', ThreadWatcher.refresh); - } - if (name === 'Show Page' || name === 'Show Unread Count' || name === 'Auto Update Thread Watcher') { - $.on(input, 'change', ThreadWatcher.fetchAuto); - } - return this.menu.addEntry(entry); - } - } - }; - - return ThreadWatcher; - -}).call(this); - -Unread = (function() { - var Unread; - - Unread = { - init: function() { - if (!(g.VIEW === 'thread' && (Conf['Unread Count'] || Conf['Unread Favicon'] || Conf['Unread Line'] || Conf['Remember Last Read Post'] || Conf['Desktop Notifications'] || Conf['Quote Threading']))) { - return; - } - if (Conf['Remember Last Read Post']) { - $.sync('Remember Last Read Post', function(enabled) { - return Conf['Remember Last Read Post'] = enabled; - }); - this.db = new DataBoard('lastReadPosts', this.sync); - } - this.hr = $.el('hr', { - id: 'unread-line', - className: 'unread-line' - }); - this.posts = new Set(); - this.postsQuotingYou = new Set(); - this.order = new RandomAccessList(); - this.position = null; - Callbacks.Thread.push({ - name: 'Unread', - cb: this.node - }); - return Callbacks.Post.push({ - name: 'Unread', - cb: this.addPost - }); - }, - node: function() { - var ID, j, len, ref, ref1, resetLink; - Unread.thread = this; - Unread.title = d.title; - Unread.lastReadPost = ((ref = Unread.db) != null ? ref.get({ - boardID: this.board.ID, - threadID: this.ID - }) : void 0) || 0; - Unread.readCount = 0; - ref1 = this.posts.keys; - for (j = 0, len = ref1.length; j < len; j++) { - ID = ref1[j]; - if (+ID <= Unread.lastReadPost) { - Unread.readCount++; - } - } - $.one(d, '4chanXInitFinished', Unread.ready); - $.on(d, 'PostsInserted', Unread.onUpdate); - $.on(d, 'ThreadUpdate', function(e) { - if (e.detail[404]) { - return Unread.update(); - } - }); - resetLink = $.el('a', { - href: 'javascript:;', - className: 'unread-reset', - textContent: 'Mark all unread' - }); - $.on(resetLink, 'click', Unread.reset); - return Header.menu.addEntry({ - el: resetLink, - order: 70 - }); - }, - ready: function() { - if (Conf['Remember Last Read Post'] && Conf['Scroll to Last Read Post']) { - Unread.scroll(); - } - Unread.setLine(true); - Unread.read(); - Unread.update(); - $.on(d, 'scroll visibilitychange', Unread.read); - if (Conf['Unread Line']) { - return $.on(d, 'visibilitychange', Unread.setLine); - } - }, - positionPrev: function() { - if (Unread.position) { - return Unread.position.prev; - } else { - return Unread.order.last; - } - }, - scroll: function() { - var bottom, hash, position; - if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { - return; - } - position = Unread.positionPrev(); - while (position) { - bottom = position.data.nodes.bottom; - if (!bottom.getBoundingClientRect().height) { - position = position.prev; - } else { - Header.scrollToIfNeeded(bottom, true); - break; - } - } - }, - reset: function() { - if (Unread.lastReadPost == null) { - return; - } - Unread.posts = new Set(); - Unread.postsQuotingYou = new Set(); - Unread.order = new RandomAccessList(); - Unread.position = null; - Unread.lastReadPost = 0; - Unread.readCount = 0; - Unread.thread.posts.forEach(function(post) { - return Unread.addPost.call(post); - }); - $.forceSync('Remember Last Read Post'); - if (Conf['Remember Last Read Post'] && (!Unread.thread.isDead || Unread.thread.isArchived)) { - Unread.db.set({ - boardID: Unread.thread.board.ID, - threadID: Unread.thread.ID, - val: 0 - }); - } - Unread.updatePosition(); - Unread.setLine(); - return Unread.update(); - }, - sync: function() { - var ID, i, j, lastReadPost, postIDs, ref, ref1; - if (Unread.lastReadPost == null) { - return; - } - lastReadPost = Unread.db.get({ - boardID: Unread.thread.board.ID, - threadID: Unread.thread.ID, - defaultValue: 0 - }); - if (!(Unread.lastReadPost < lastReadPost)) { - return; - } - Unread.lastReadPost = lastReadPost; - postIDs = Unread.thread.posts.keys; - for (i = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 1) { - ID = +postIDs[i]; - if (!Unread.thread.posts.get(ID).isFetchedQuote) { - if (ID > Unread.lastReadPost) { - break; - } - Unread.posts["delete"](ID); - Unread.postsQuotingYou["delete"](ID); - } - Unread.readCount++; - } - Unread.updatePosition(); - Unread.setLine(); - return Unread.update(); - }, - addPost: function() { - if (this.isFetchedQuote || this.isClone) { - return; - } - Unread.order.push(this); - if (this.ID <= Unread.lastReadPost || this.isHidden || QuoteYou.isYou(this)) { - return; - } - Unread.posts.add((Unread.posts.last = this.ID)); - Unread.addPostQuotingYou(this); - return Unread.position != null ? Unread.position : Unread.position = Unread.order[this.ID]; - }, - addPostQuotingYou: function(post) { - var j, len, quotelink, ref, ref1; - ref = post.nodes.quotelinks; - for (j = 0, len = ref.length; j < len; j++) { - quotelink = ref[j]; - if (!((ref1 = QuoteYou.db) != null ? ref1.get(Get.postDataFromLink(quotelink)) : void 0)) { - continue; - } - Unread.postsQuotingYou.add((Unread.postsQuotingYou.last = post.ID)); - Unread.openNotification(post); - return; - } - }, - openNotification: function(post, predicate) { - var notif; - if (predicate == null) { - predicate = ' replied to you'; - } - if (!Header.areNotificationsEnabled) { - return; - } - notif = new Notification("" + post.info.nameBlock + predicate, { - body: post.commentDisplay(), - icon: Favicon.logo - }); - notif.onclick = function() { - Header.scrollToIfNeeded(post.nodes.bottom, true); - return window.focus(); - }; - return notif.onshow = function() { - return setTimeout(function() { - return notif.close(); - }, 7 * $.SECOND); - }; - }, - onUpdate: function() { - return $.queueTask(function() { - Unread.setLine(); - Unread.read(); - return Unread.update(); - }); - }, - readSinglePost: function(post) { - var ID; - ID = post.ID; - if (!Unread.posts.has(ID)) { - return; - } - Unread.posts["delete"](ID); - Unread.postsQuotingYou["delete"](ID); - Unread.updatePosition(); - Unread.saveLastReadPost(); - return Unread.update(); - }, - read: $.debounce(100, function(e) { - var ID, bottom, count, data, ref; - if (!Unread.posts.size && Unread.readCount !== Unread.thread.posts.keys.length) { - Unread.saveLastReadPost(); - } - if (d.hidden || !Unread.posts.size) { - return; - } - count = 0; - while (Unread.position) { - ref = Unread.position, ID = ref.ID, data = ref.data; - bottom = data.nodes.bottom; - if (!(!bottom.getBoundingClientRect().height || Header.getBottomOf(bottom) > -1)) { - break; - } - count++; - Unread.posts["delete"](ID); - Unread.postsQuotingYou["delete"](ID); - Unread.position = Unread.position.next; - } - if (!count) { - return; - } - Unread.updatePosition(); - Unread.saveLastReadPost(); - if (e) { - return Unread.update(); - } - }), - updatePosition: function() { - while (Unread.position && !Unread.posts.has(Unread.position.ID)) { - Unread.position = Unread.position.next; - } - }, - saveLastReadPost: $.debounce(2 * $.SECOND, function() { - var ID, i, j, postIDs, ref, ref1; - $.forceSync('Remember Last Read Post'); - if (!(Conf['Remember Last Read Post'] && Unread.db)) { - return; - } - postIDs = Unread.thread.posts.keys; - for (i = j = ref = Unread.readCount, ref1 = postIDs.length; j < ref1; i = j += 1) { - ID = +postIDs[i]; - if (!Unread.thread.posts.get(ID).isFetchedQuote) { - if (Unread.posts.has(ID)) { - break; - } - Unread.lastReadPost = ID; - } - Unread.readCount++; - } - if (Unread.thread.isDead && !Unread.thread.isArchived) { - return; - } - return Unread.db.set({ - boardID: Unread.thread.board.ID, - threadID: Unread.thread.ID, - val: Unread.lastReadPost - }); - }), - setLine: function(force) { - var node, oldPosition, ref; - if (!Conf['Unread Line']) { - return; - } - if (Unread.hr.hidden || d.hidden || (force === true)) { - oldPosition = Unread.linePosition; - if ((Unread.linePosition = Unread.positionPrev())) { - if (Unread.linePosition !== oldPosition) { - node = Unread.linePosition.data.nodes.bottom; - if (((ref = node.nextSibling) != null ? ref.tagName : void 0) === 'BR') { - node = node.nextSibling; - } - $.after(node, Unread.hr); - } - } else { - $.rm(Unread.hr); - } - } - return Unread.hr.hidden = Unread.linePosition === Unread.order.last; - }, - update: function() { - var count, countQuotingYou, isDead, titleCount, titleDead, titleQuotingYou; - count = Unread.posts.size; - countQuotingYou = Unread.postsQuotingYou.size; - if (Conf['Unread Count']) { - titleQuotingYou = Conf['Quoted Title'] && countQuotingYou ? '(!) ' : ''; - titleCount = count || !Conf['Hide Unread Count at (0)'] ? "(" + count + ") " : ''; - titleDead = Unread.thread.isDead ? Unread.title.replace('-', (Unread.thread.isArchived ? '- Archived -' : '- 404 -')) : Unread.title; - d.title = "" + titleQuotingYou + titleCount + titleDead; - } - Unread.saveThreadWatcherCount(); - if (Conf['Unread Favicon'] && g.SITE.software === 'yotsuba') { - isDead = Unread.thread.isDead; - return Favicon.set((countQuotingYou ? (isDead ? 'unreadDeadY' : 'unreadY') : count ? (isDead ? 'unreadDead' : 'unread') : (isDead ? 'dead' : 'default'))); - } - }, - saveThreadWatcherCount: $.debounce(2 * $.SECOND, function() { - var i, j, posts, quotingYou, ref; - $.forceSync('Remember Last Read Post'); - if (Conf['Remember Last Read Post'] && (!Unread.thread.isDead || Unread.thread.isArchived)) { - quotingYou = !Conf['Require OP Quote Link'] && QuoteYou.isYou(Unread.thread.OP) ? Unread.posts : Unread.postsQuotingYou; - if (!quotingYou.size) { - quotingYou.last = 0; - } else if (!quotingYou.has(quotingYou.last)) { - quotingYou.last = 0; - posts = Unread.thread.posts.keys; - for (i = j = ref = posts.length - 1; j >= 0; i = j += -1) { - if (quotingYou.has(+posts[i])) { - quotingYou.last = posts[i]; - break; - } - } - } - return ThreadWatcher.update(g.SITE.ID, Unread.thread.board.ID, Unread.thread.ID, { - last: Unread.thread.lastPost, - isDead: Unread.thread.isDead, - isArchived: Unread.thread.isArchived, - unread: Unread.posts.size, - quotingYou: quotingYou.last || 0 - }); - } - }) - }; - - return Unread; - -}).call(this); - -UnreadIndex = (function() { - var UnreadIndex; - - UnreadIndex = { - lastReadPost: $.dict(), - hr: $.dict(), - markReadLink: $.dict(), - init: function() { - if (!(g.VIEW === 'index' && Conf['Remember Last Read Post'] && Conf['Unread Line in Index'])) { - return; - } - this.enabled = true; - this.db = new DataBoard('lastReadPosts', this.sync); - Callbacks.Thread.push({ - name: 'Unread Line in Index', - cb: this.node - }); - $.on(d, 'IndexRefreshInternal', this.onIndexRefresh); - return $.on(d, 'PostsInserted PostsRemoved', this.onPostsInserted); - }, - node: function() { - UnreadIndex.lastReadPost[this.fullID] = UnreadIndex.db.get({ - boardID: this.board.ID, - threadID: this.ID - }) || 0; - if (!Index.enabled) { - return UnreadIndex.update(this); - } - }, - onIndexRefresh: function(e) { - var i, len, ref, results, thread, threadID; - if (e.detail.isCatalog) { - return; - } - ref = e.detail.threadIDs; - results = []; - for (i = 0, len = ref.length; i < len; i++) { - threadID = ref[i]; - thread = g.threads.get(threadID); - results.push(UnreadIndex.update(thread)); - } - return results; - }, - onPostsInserted: function(e) { - var ref, ref1, thread, wasVisible; - if (e.target === Index.root) { - return; - } - thread = Get.threadFromNode(e.target); - if (!thread || thread.nodes.root !== e.target) { - return; - } - wasVisible = !!((ref = UnreadIndex.hr[thread.fullID]) != null ? ref.parentNode : void 0); - UnreadIndex.update(thread); - if (Conf['Scroll to Last Read Post'] && e.type === 'PostsInserted' && !wasVisible && !!((ref1 = UnreadIndex.hr[thread.fullID]) != null ? ref1.parentNode : void 0)) { - return Header.scrollToIfNeeded(UnreadIndex.hr[thread.fullID], true); - } - }, - sync: function() { - return g.threads.forEach(function(thread) { - var lastReadPost, ref; - lastReadPost = UnreadIndex.db.get({ - boardID: thread.board.ID, - threadID: thread.ID - }) || 0; - if (lastReadPost !== UnreadIndex.lastReadPost[thread.fullID]) { - UnreadIndex.lastReadPost[thread.fullID] = lastReadPost; - if ((ref = thread.nodes.root) != null ? ref.parentNode : void 0) { - return UnreadIndex.update(thread); - } - } - }); - }, - update: function(thread) { - var divider, firstUnread, hasUnread, hr, lastReadPost, link, repliesRead, repliesShown; - lastReadPost = UnreadIndex.lastReadPost[thread.fullID]; - repliesShown = 0; - repliesRead = 0; - firstUnread = null; - thread.posts.forEach(function(post) { - if (post.isReply && thread.nodes.root.contains(post.nodes.root)) { - repliesShown++; - if (post.ID <= lastReadPost) { - return repliesRead++; - } else if ((!firstUnread || post.ID < firstUnread.ID) && !post.isHidden && !QuoteYou.isYou(post)) { - return firstUnread = post; - } - } - }); - hr = UnreadIndex.hr[thread.fullID]; - if (firstUnread && (repliesRead || (lastReadPost === thread.OP.ID && (!$(g.SITE.selectors.summary, thread.nodes.root) || thread.ID in ExpandThread.statuses)))) { - if (!hr) { - hr = UnreadIndex.hr[thread.fullID] = $.el('hr', { - className: 'unread-line' - }); - } - $.before(firstUnread.nodes.root, hr); - } else { - $.rm(hr); - } - hasUnread = repliesShown ? firstUnread || !repliesRead : Index.enabled ? thread.lastPost > lastReadPost : thread.OP.ID > lastReadPost; - thread.nodes.root.classList.toggle('unread-thread', hasUnread); - link = UnreadIndex.markReadLink[thread.fullID]; - if (!link) { - link = UnreadIndex.markReadLink[thread.fullID] = $.el('a', { - className: 'unread-mark-read brackets-wrap', - href: 'javascript:;', - textContent: 'Mark Read' - }); - $.on(link, 'click', UnreadIndex.markRead); - } - if ((divider = $(g.SITE.selectors.threadDivider, thread.nodes.root))) { - return $.before(divider, link); - } else { - return $.add(thread.nodes.root, link); - } - }, - markRead: function() { - var thread; - thread = Get.threadFromNode(this); - UnreadIndex.lastReadPost[thread.fullID] = thread.lastPost; - UnreadIndex.db.set({ - boardID: thread.board.ID, - threadID: thread.ID, - val: thread.lastPost - }); - $.rm(UnreadIndex.hr[thread.fullID]); - thread.nodes.root.classList.remove('unread-thread'); - return ThreadWatcher.update(g.SITE.ID, thread.board.ID, thread.ID, { - last: thread.lastPost, - unread: 0, - quotingYou: 0 - }); - } - }; - - return UnreadIndex; - -}).call(this); - -Captcha = {}; - -(function() { - Captcha.cache = { - init: function() { - $.on(d, 'SaveCaptcha', (function(_this) { - return function(e) { - return _this.saveAPI(e.detail); - }; - })(this)); - return $.on(d, 'NoCaptcha', (function(_this) { - return function(e) { - return _this.noCaptcha(e.detail); - }; - })(this)); - }, - captchas: [], - getCount: function() { - return this.captchas.length; - }, - neededRaw: function() { - return !(this.haveCookie() || this.captchas.length || QR.req || this.submitCB) && (QR.posts.length > 1 || Conf['Auto-load captcha'] || !QR.posts[0].isOnlyQuotes() || QR.posts[0].file); - }, - needed: function() { - return this.neededRaw() && $.event('LoadCaptcha'); - }, - prerequest: function() { - if (!Conf['Prerequest Captcha']) { - return; - } - return $.queueTask((function(_this) { - return function() { - var isReply; - if (!_this.prerequested && _this.neededRaw() && !$.event('LoadCaptcha') && !QR.captcha.occupied() && QR.cooldown.seconds <= 60 && QR.selected === QR.posts[QR.posts.length - 1] && !QR.selected.isOnlyQuotes()) { - isReply = QR.selected.thread !== 'new'; - if (!$.event('RequestCaptcha', { - isReply: isReply - })) { - _this.prerequested = true; - _this.submitCB = function(captcha) { - if (captcha) { - return _this.save(captcha); - } - }; - return _this.updateCount(); - } - } - }; - })(this)); - }, - haveCookie: function() { - return /\b_ct=/.test(d.cookie) && QR.posts[0].thread !== 'new'; - }, - getOne: function() { - var captcha; - delete this.prerequested; - this.clear(); - if ((captcha = this.captchas.shift())) { - this.count(); - return captcha; - } else { - return null; - } - }, - request: function(isReply) { - if (!this.submitCB) { - if ($.event('RequestCaptcha', { - isReply: isReply - })) { - return; - } - } - return (function(_this) { - return function(cb) { - _this.submitCB = cb; - return _this.updateCount(); - }; - })(this); - }, - abort: function() { - if (this.submitCB) { - delete this.submitCB; - $.event('AbortCaptcha'); - return this.updateCount(); - } - }, - saveAPI: function(captcha) { - var cb; - if ((cb = this.submitCB)) { - delete this.submitCB; - cb(captcha); - return this.updateCount(); - } else { - return this.save(captcha); - } - }, - noCaptcha: function(detail) { - var cb; - if ((cb = this.submitCB)) { - if (!this.haveCookie() || (detail != null ? detail.error : void 0)) { - QR.error((detail != null ? detail.error : void 0) || 'Failed to retrieve captcha.'); - QR.captcha.setup(d.activeElement === QR.nodes.status); - } - delete this.submitCB; - cb(); - return this.updateCount(); - } - }, - save: function(captcha) { - var cb; - if ((cb = this.submitCB)) { - this.abort(); - cb(captcha); - return; - } - this.captchas.push(captcha); - this.captchas.sort(function(a, b) { - return a.timeout - b.timeout; - }); - return this.count(); - }, - clear: function() { - var captcha, i, j, len, now, ref; - if (this.captchas.length) { - now = Date.now(); - ref = this.captchas; - for (i = j = 0, len = ref.length; j < len; i = ++j) { - captcha = ref[i]; - if (captcha.timeout > now) { - break; - } - } - if (i) { - this.captchas = this.captchas.slice(i); - return this.count(); - } - } - }, - count: function() { - clearTimeout(this.timer); - if (this.captchas.length) { - this.timer = setTimeout(this.clear.bind(this), this.captchas[0].timeout - Date.now()); - } - return this.updateCount(); - }, - updateCount: function() { - return $.event('CaptchaCount', this.captchas.length); - } - }; - -}).call(this); - -(function() { - Captcha.replace = { - init: function() { - var ref; - if (!(g.SITE.software === 'yotsuba' && d.cookie.indexOf('pass_enabled=1') < 0)) { - return; - } - if (Conf['Force Noscript Captcha'] && Main.jsEnabled) { - $.ready(Captcha.replace.noscript); - return; - } - if (Conf['captchaLanguage'].trim()) { - if ((ref = location.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') { - return $.onExists(doc, '#captchaFormPart', function(node) { - return $.onExists(node, 'iframe[src^="https://www.google.com/recaptcha/"]', Captcha.replace.iframe); - }); - } else { - return $.onExists(doc, 'iframe[src^="https://www.google.com/recaptcha/"]', Captcha.replace.iframe); - } - } - }, - noscript: function() { - var insert, noscript, original, span, toggle; - if (!((original = $('#g-recaptcha')) && (noscript = $('noscript', original.parentNode)))) { - return; - } - span = $.el('span', { - id: 'captcha-forced-noscript' - }); - $.replace(noscript, span); - $.rm(original); - insert = function() { - span.innerHTML = noscript.textContent; - return Captcha.replace.iframe($('iframe[src^="https://www.google.com/recaptcha/"]', span)); - }; - if ((toggle = $('#togglePostFormLink a, #form-link'))) { - return $.on(toggle, 'click', insert); - } else { - return insert(); - } - }, - iframe: function(iframe) { - var lang, src; - if ((lang = Conf['captchaLanguage'].trim())) { - src = /[?&]hl=/.test(iframe.src) ? iframe.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent(lang)) : iframe.src + ("&hl=" + (encodeURIComponent(lang))); - if (iframe.src !== src) { - iframe.src = src; - } - } - } - }; - -}).call(this); - -(function() { - Captcha.t = { - init: function() { - var root; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#t-root') || !$.id('postForm'))) { - return; - } - root = $.el('div', { - className: 'captcha-root' - }); - this.nodes = { - root: root - }; - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-t'); - return $.after(QR.nodes.com.parentNode, root); - }, - moreNeeded: function() {}, - getThread: function() { - var boardID, threadID; - boardID = g.BOARD.ID; - if (QR.posts[0].thread === 'new') { - threadID = '0'; - } else { - threadID = '' + QR.posts[0].thread; - } - return { - boardID: boardID, - threadID: threadID - }; - }, - setup: function(focus) { - if (!this.isEnabled) { - return; - } - if (!this.nodes.container) { - this.nodes.container = $.el('div', { - className: 'captcha-container' - }); - $.prepend(this.nodes.root, this.nodes.container); - Captcha.t.currentThread = Captcha.t.getThread(); - $.global(function() { - var el; - el = document.querySelector('#qr .captcha-container'); - window.TCaptcha.init(el, this.boardID, +this.threadID); - return window.TCaptcha.setErrorCb(function(err) { - return window.dispatchEvent(new CustomEvent('CreateNotification', { - detail: { - type: 'warning', - content: '' + err - } - })); - }); - }, Captcha.t.currentThread); - } - if (focus) { - return $('#t-resp').focus(); - } - }, - destroy: function() { - if (!(this.isEnabled && this.nodes.container)) { - return; - } - $.global(function() { - return window.TCaptcha.destroy(); - }); - $.rm(this.nodes.container); - return delete this.nodes.container; - }, - updateThread: function() { - var boardID, newThread, ref, threadID; - if (!this.isEnabled) { - return; - } - ref = Captcha.t.currentThread || {}, boardID = ref.boardID, threadID = ref.threadID; - newThread = Captcha.t.getThread(); - if (!(newThread.boardID === boardID && newThread.threadID === threadID)) { - Captcha.t.destroy(); - return Captcha.t.setup(); - } - }, - getOne: function() { - var el, i, key, len, ref, response; - response = {}; - if (this.nodes.container) { - ref = ['t-response', 't-challenge']; - for (i = 0, len = ref.length; i < len; i++) { - key = ref[i]; - response[key] = $("[name='" + key + "']", this.nodes.container).value; - } - } - if (!response['t-response'] && !((el = $('#t-msg')) && /Verification not required/i.test(el.textContent))) { - response = null; - } - return response; - }, - setUsed: function() { - if (!this.isEnabled) { - return; - } - if (this.nodes.container) { - return $.global(function() { - return window.TCaptcha.clearChallenge(); - }); - } - }, - occupied: function() { - return !!this.nodes.container; - } - }; - -}).call(this); - -(function() { - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Captcha.v2 = { - lifetime: 2 * $.MINUTE, - init: function() { - var counter, root; - if (d.cookie.indexOf('pass_enabled=1') >= 0) { - return; - } - if (!(this.isEnabled = !!$('#g-recaptcha, #captcha-forced-noscript') || !$.id('postForm'))) { - return; - } - if ((this.noscript = Conf['Force Noscript Captcha'] || !Main.jsEnabled)) { - $.addClass(QR.nodes.el, 'noscript-captcha'); - } - Captcha.cache.init(); - $.on(d, 'CaptchaCount', this.count.bind(this)); - root = $.el('div', { - className: 'captcha-root' - }); - $.extend(root, {innerHTML: "
      "}); - counter = $('.captcha-counter > a', root); - this.nodes = { - root: root, - counter: counter - }; - this.count(); - $.addClass(QR.nodes.el, 'has-captcha', 'captcha-v2'); - $.after(QR.nodes.com.parentNode, root); - $.on(counter, 'click', this.toggle.bind(this)); - $.on(counter, 'keydown', (function(_this) { - return function(e) { - if (Keybinds.keyCode(e) !== 'Space') { - return; - } - _this.toggle(); - e.preventDefault(); - return e.stopPropagation(); - }; - })(this)); - return $.on(window, 'captcha:success', (function(_this) { - return function() { - return $.queueTask(function() { - return _this.save(false); - }); - }; - })(this)); - }, - timeouts: {}, - prevNeeded: 0, - noscriptURL: function() { - var lang, url; - url = 'https://www.google.com/recaptcha/api/fallback?k=6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc'; - if ((lang = Conf['captchaLanguage'].trim())) { - url += "&hl=" + (encodeURIComponent(lang)); - } - return url; - }, - moreNeeded: function() { - return $.queueTask((function(_this) { - return function() { - var needed; - needed = Captcha.cache.needed(); - if (needed && !_this.prevNeeded) { - _this.setup(QR.cooldown.auto && d.activeElement === QR.nodes.status); - } - return _this.prevNeeded = needed; - }; - })(this)); - }, - toggle: function() { - if (this.nodes.container && !this.timeouts.destroy) { - return this.destroy(); - } else { - return this.setup(true, true); - } - }, - setup: function(focus, force) { - if (!(this.isEnabled && (Captcha.cache.needed() || force))) { - return; - } - if (focus) { - $.addClass(QR.nodes.el, 'focus'); - this.nodes.counter.focus(); - } - if (this.timeouts.destroy) { - clearTimeout(this.timeouts.destroy); - delete this.timeouts.destroy; - return this.reload(); - } - if (this.nodes.container) { - $.queueTask((function(_this) { - return function() { - var iframe; - if (_this.nodes.container && d.activeElement === _this.nodes.counter && (iframe = $('iframe[src^="https://www.google.com/recaptcha/"]', _this.nodes.container))) { - iframe.focus(); - return QR.focus(); - } - }; - })(this)); - return; - } - this.nodes.container = $.el('div', { - className: 'captcha-container' - }); - $.prepend(this.nodes.root, this.nodes.container); - new MutationObserver(this.afterSetup.bind(this)).observe(this.nodes.container, { - childList: true, - subtree: true - }); - if (this.noscript) { - return this.setupNoscript(); - } else { - return this.setupJS(); - } - }, - setupNoscript: function() { - var div, iframe, textarea; - iframe = $.el('iframe', { - id: 'qr-captcha-iframe', - scrolling: 'no', - src: this.noscriptURL() - }); - div = $.el('div'); - textarea = $.el('textarea'); - $.add(div, textarea); - return $.add(this.nodes.container, [iframe, div]); - }, - setupJS: function() { - return $.global(function() { - var cbNative, render, script; - render = function() { - var classList, container; - classList = document.documentElement.classList; - container = document.querySelector('#qr .captcha-container'); - return container.dataset.widgetID = window.grecaptcha.render(container, { - sitekey: '6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc', - theme: classList.contains('tomorrow') || classList.contains('spooky') || classList.contains('dark-captcha') ? 'dark' : 'light', - callback: function(response) { - return window.dispatchEvent(new CustomEvent('captcha:success', { - detail: response - })); - } - }); - }; - if (window.grecaptcha) { - return render(); - } else { - cbNative = window.onRecaptchaLoaded; - window.onRecaptchaLoaded = function() { - render(); - return cbNative(); - }; - if (!document.head.querySelector('script[src^="https://www.google.com/recaptcha/api.js"]')) { - script = document.createElement('script'); - script.src = 'https://www.google.com/recaptcha/api.js?onload=onRecaptchaLoaded&render=explicit'; - return document.head.appendChild(script); - } - } - }); - }, - afterSetup: function(mutations) { - var i, iframe, j, len, len1, mutation, node, ref, textarea; - for (i = 0, len = mutations.length; i < len; i++) { - mutation = mutations[i]; - ref = mutation.addedNodes; - for (j = 0, len1 = ref.length; j < len1; j++) { - node = ref[j]; - if ((iframe = $.x('./descendant-or-self::iframe[starts-with(@src, "https://www.google.com/recaptcha/")]', node))) { - this.setupIFrame(iframe); - } - if ((textarea = $.x('./descendant-or-self::textarea', node))) { - this.setupTextArea(textarea); - } - } - } - }, - setupIFrame: function(iframe) { - var ref, ref1; - if (!doc.contains(iframe)) { - return; - } - Captcha.replace.iframe(iframe); - $.addClass(QR.nodes.el, 'captcha-open'); - this.fixQRPosition(); - $.on(iframe, 'load', this.fixQRPosition); - if (d.activeElement === this.nodes.counter) { - iframe.focus(); - } - if (((ref = $.engine) === 'blink' || ref === 'edge') && (ref1 = iframe.parentNode, indexOf.call($$('#qr .captcha-container > div > div:first-of-type'), ref1) >= 0)) { - return $.on(iframe.parentNode, 'scroll', function() { - return this.scrollTop = 0; - }); - } - }, - fixQRPosition: function() { - if (QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight) { - QR.nodes.el.style.top = ''; - return QR.nodes.el.style.bottom = '0px'; - } - }, - setupTextArea: function(textarea) { - return $.one(textarea, 'input', (function(_this) { - return function() { - return _this.save(true); - }; - })(this)); - }, - destroy: function() { - if (!this.isEnabled) { - return; - } - delete this.timeouts.destroy; - $.rmClass(QR.nodes.el, 'captcha-open'); - if (this.nodes.container) { - $.global(function() { - var container; - container = document.querySelector('#qr .captcha-container'); - return window.grecaptcha.reset(container.dataset.widgetID); - }); - $.rm(this.nodes.container); - return delete this.nodes.container; - } - }, - getOne: function(isReply) { - return Captcha.cache.getOne(isReply); - }, - save: function(pasted, token) { - var base, focus, ref; - Captcha.cache.save({ - response: token || $('textarea', this.nodes.container).value, - timeout: Date.now() + this.lifetime - }); - focus = ((ref = d.activeElement) != null ? ref.nodeName : void 0) === 'IFRAME' && /https?:\/\/www\.google\.com\/recaptcha\//.test(d.activeElement.src); - if (Captcha.cache.needed()) { - if (focus) { - if (QR.cooldown.auto || Conf['Post on Captcha Completion']) { - this.nodes.counter.focus(); - } else { - QR.nodes.status.focus(); - } - } - this.reload(); - } else { - if (pasted) { - this.destroy(); - } else { - if ((base = this.timeouts).destroy == null) { - base.destroy = setTimeout(this.destroy.bind(this), 3 * $.SECOND); - } - } - if (focus) { - QR.nodes.status.focus(); - } - } - if (Conf['Post on Captcha Completion'] && !QR.cooldown.auto) { - return QR.submit(); - } - }, - count: function() { - var count, loading; - count = Captcha.cache.getCount(); - loading = Captcha.cache.submitCB ? '...' : ''; - this.nodes.counter.textContent = "Captchas: " + count + loading; - return this.moreNeeded(); - }, - reload: function() { - if ($('iframe[src^="https://www.google.com/recaptcha/api/fallback?"]', this.nodes.container)) { - this.destroy(); - return this.setup(false, true); - } else { - return $.global(function() { - var container; - container = document.querySelector('#qr .captcha-container'); - return window.grecaptcha.reset(container.dataset.widgetID); - }); - } - }, - occupied: function() { - return !!this.nodes.container && !this.timeouts.destroy; - } - }; - -}).call(this); - -PassLink = (function() { - var PassLink; - - PassLink = { - init: function() { - if (!(g.SITE.software === 'yotsuba' && Conf['Pass Link'])) { - return; - } - return Main.ready(this.ready); - }, - ready: function() { - var passLink, styleSelector; - if (!(styleSelector = $.id('styleSelector'))) { - return; - } - passLink = $.el('span', { - className: 'brackets-wrap pass-link-container' - }); - $.extend(passLink, {innerHTML: "4chan Pass"}); - $.on(passLink.firstElementChild, 'click', function() { - return window.open("//sys." + (location.hostname.split('.')[1]) + ".org/auth", Date.now(), 'width=500,height=280,toolbar=0'); - }); - return $.before(styleSelector.previousSibling, [passLink, $.tn('\u00A0\u00A0')]); - } - }; - - return PassLink; - -}).call(this); - -PostRedirect = (function() { - var PostRedirect; - - PostRedirect = { - init: function() { - return $.on(d, 'QRPostSuccessful', (function(_this) { - return function(e) { - if (!e.detail.redirect) { - return; - } - _this.event = e; - _this.delays = 0; - return $.queueTask(function() { - if (e === _this.event && _this.delays === 0) { - return location.href = e.detail.redirect; - } - }); - }; - })(this)); - }, - delays: 0, - delay: function() { - var e; - if (!this.event) { - return null; - } - e = this.event; - this.delays++; - return (function(_this) { - return function() { - if (e !== _this.event) { - return; - } - _this.delays--; - if (_this.delays === 0) { - return location.href = e.detail.redirect; - } - }; - })(this); - } - }; - - return PostRedirect; - -}).call(this); - -PostSuccessful = (function() { - var PostSuccessful; - - PostSuccessful = { - init: function() { - if (!Conf['Remember Your Posts']) { - return; - } - return $.ready(this.ready); - }, - ready: function() { - var _, db, postID, ref, threadID; - if (d.title !== 'Post successful!') { - return; - } - ref = $('h1').nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref[0], threadID = ref[1], postID = ref[2]; - postID = +postID; - threadID = +threadID || postID; - db = new DataBoard('yourPosts'); - return db.set({ - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID, - val: true - }); - } - }; - - return PostSuccessful; - -}).call(this); - -QR = (function() { - var QR, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - QR = { - mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], - validExtension: /\.(jpe?g|png|gif|pdf|swf|webm)$/i, - typeFromExtension: { - 'jpg': 'image/jpeg', - 'jpeg': 'image/jpeg', - 'png': 'image/png', - 'gif': 'image/gif', - 'pdf': 'application/pdf', - 'swf': 'application/vnd.adobe.flash.movie', - 'webm': 'video/webm' - }, - extensionFromType: { - 'image/jpeg': 'jpg', - 'image/png': 'png', - 'image/gif': 'gif', - 'application/pdf': 'pdf', - 'application/vnd.adobe.flash.movie': 'swf', - 'application/x-shockwave-flash': 'swf', - 'video/webm': 'webm' - }, - init: function() { - var sc; - if (!Conf['Quick Reply']) { - return; - } - this.posts = []; - $.on(d, '4chanXInitFinished', function() { - return BoardConfig.ready(QR.initReady); - }); - Callbacks.Post.push({ - name: 'Quick Reply', - cb: this.node - }); - this.shortcut = sc = $.el('a', { - className: 'fa fa-comment-o disabled', - textContent: 'QR', - title: 'Quick Reply', - href: 'javascript:;' - }); - $.on(sc, 'click', function() { - if (!QR.postingIsEnabled) { - return; - } - if (Conf['Persistent QR'] || !QR.nodes || QR.nodes.el.hidden) { - QR.open(); - return QR.nodes.com.focus(); - } else { - return QR.close(); - } - }); - return Header.addShortcut('qr', sc, 540); - }, - initReady: function() { - var captchaVersion, config, link, linkBot, navLinksBot, origToggle, prop; - captchaVersion = $('#g-recaptcha, #captcha-forced-noscript') ? 'v2' : 't'; - QR.captcha = Captcha[captchaVersion]; - QR.postingIsEnabled = true; - config = g.BOARD.config; - prop = function(key, def) { - var ref; - return +((ref = config[key]) != null ? ref : def); - }; - QR.min_width = prop('min_image_width', 1); - QR.min_height = prop('min_image_height', 1); - QR.max_width = QR.max_height = 10000; - QR.max_size = prop('max_filesize', 4194304); - QR.max_size_video = prop('max_webm_filesize', QR.max_size); - QR.max_comment = prop('max_comment_chars', 2000); - QR.max_width_video = QR.max_height_video = 2048; - QR.max_duration_video = prop('max_webm_duration', 120); - QR.forcedAnon = !!config.forced_anon; - QR.spoiler = !!config.spoilers; - if ((origToggle = $.id('togglePostFormLink'))) { - link = $.el('h1', { - className: "qr-link-container" - }); - $.extend(link, {innerHTML: "" + ((g.VIEW === "thread") ? "Reply to Thread" : "Start a Thread") + ""}); - QR.link = link.firstElementChild; - $.on(link.firstChild, 'click', function() { - QR.open(); - return QR.nodes.com.focus(); - }); - $.before(origToggle, link); - origToggle.firstElementChild.textContent = 'Original Form'; - } - if (g.VIEW === 'thread') { - linkBot = $.el('div', { - className: "brackets-wrap qr-link-container-bottom" - }); - $.extend(linkBot, {innerHTML: "Reply to Thread"}); - $.on(linkBot.firstElementChild, 'click', function() { - QR.open(); - return QR.nodes.com.focus(); - }); - if ((navLinksBot = $('.navLinksBot'))) { - $.prepend(navLinksBot, linkBot); - } - } - $.on(d, 'QRGetFile', QR.getFile); - $.on(d, 'QRDrawFile', QR.drawFile); - $.on(d, 'QRSetFile', QR.setFile); - $.on(d, 'paste', QR.paste); - $.on(d, 'dragover', QR.dragOver); - $.on(d, 'drop', QR.dropFile); - $.on(d, 'dragstart dragend', QR.drag); - $.on(d, 'IndexRefreshInternal', QR.generatePostableThreadsList); - $.on(d, 'ThreadUpdate', QR.statusCheck); - if (!Conf['Persistent QR']) { - return; - } - QR.open(); - if (Conf['Auto Hide QR']) { - return QR.hide(); - } - }, - statusCheck: function() { - var thread; - if (!QR.nodes) { - return; - } - thread = QR.posts[0].thread; - if (thread !== 'new' && g.threads.get(g.BOARD + "." + thread).isDead) { - return QR.abort(); - } else { - return QR.status(); - } - }, - node: function() { - $.on(this.nodes.quote, 'click', QR.quote); - if (this.isFetchedQuote) { - return QR.generatePostableThreadsList(); - } - }, - open: function() { - var err; - if (QR.nodes) { - if (QR.nodes.el.hidden) { - QR.captcha.setup(); - } - QR.nodes.el.hidden = false; - QR.unhide(); - } else { - try { - QR.dialog(); - } catch (error) { - err = error; - delete QR.nodes; - Main.handleErrors({ - message: 'Quick Reply dialog creation crashed.', - error: err - }); - return; - } - } - return $.rmClass(QR.shortcut, 'disabled'); - }, - close: function() { - var j, len, post, ref; - if (QR.req) { - QR.abort(); - return; - } - QR.nodes.el.hidden = true; - QR.cleanNotifications(); - QR.blur(); - $.rmClass(QR.nodes.el, 'dump'); - $.addClass(QR.shortcut, 'disabled'); - new QR.post(true); - ref = QR.posts.splice(0, QR.posts.length - 1); - for (j = 0, len = ref.length; j < len; j++) { - post = ref[j]; - post["delete"](); - } - QR.cooldown.auto = false; - QR.status(); - return QR.captcha.destroy(); - }, - focus: function() { - return $.queueTask(function() { - if (!QR.inBubble()) { - QR.hasFocus = d.activeElement && QR.nodes.el.contains(d.activeElement); - return QR.nodes.el.classList.toggle('focus', QR.hasFocus); - } - }); - }, - inBubble: function() { - var bubbles, ref; - bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return (ref = d.activeElement, indexOf.call(bubbles, ref) >= 0) || bubbles.some(function(el) { - return getComputedStyle(el).visibility !== 'hidden' && el.getBoundingClientRect().bottom > 0; - }); - }, - hide: function() { - QR.blur(); - $.addClass(QR.nodes.el, 'autohide'); - return QR.nodes.autohide.checked = true; - }, - unhide: function() { - $.rmClass(QR.nodes.el, 'autohide'); - return QR.nodes.autohide.checked = false; - }, - toggleHide: function() { - if (this.checked) { - return QR.hide(); - } else { - return QR.unhide(); - } - }, - blur: function() { - if (QR.nodes.el.contains(d.activeElement)) { - return d.activeElement.blur(); - } - }, - toggleSJIS: function(e) { - e.preventDefault(); - Conf['sjisPreview'] = !Conf['sjisPreview']; - $.set('sjisPreview', Conf['sjisPreview']); - return QR.nodes.el.classList.toggle('sjis-preview', Conf['sjisPreview']); - }, - texPreviewShow: function() { - if ($.hasClass(QR.nodes.el, 'tex-preview')) { - return QR.texPreviewHide(); - } - $.addClass(QR.nodes.el, 'tex-preview'); - QR.nodes.texPreview.textContent = QR.nodes.com.value; - return $.event('mathjax', null, QR.nodes.texPreview); - }, - texPreviewHide: function() { - return $.rmClass(QR.nodes.el, 'tex-preview'); - }, - addPost: function() { - var wasOpen; - wasOpen = QR.nodes && !QR.nodes.el.hidden; - QR.open(); - if (wasOpen) { - $.addClass(QR.nodes.el, 'dump'); - new QR.post(true); - } - return QR.nodes.com.focus(); - }, - setCustomCooldown: function(enabled) { - Conf['customCooldownEnabled'] = enabled; - QR.cooldown.customCooldown = enabled; - return QR.nodes.customCooldown.classList.toggle('disabled', !enabled); - }, - toggleCustomCooldown: function() { - var enabled; - enabled = $.hasClass(QR.nodes.customCooldown, 'disabled'); - QR.setCustomCooldown(enabled); - return $.set('customCooldownEnabled', enabled); - }, - error: function(err, focusOverride) { - var el, notice, notif; - QR.open(); - if (typeof err === 'string') { - el = $.tn(err); - } else { - el = err; - el.removeAttribute('style'); - } - notice = new Notice('warning', el); - QR.notifications.push(notice); - if (!Header.areNotificationsEnabled) { - if (d.hidden && !QR.cooldown.auto) { - return alert(el.textContent); - } - } else if (d.hidden || !(focusOverride || d.hasFocus())) { - notif = new Notification(el.textContent, { - body: el.textContent, - icon: Favicon.logo - }); - notif.onclick = function() { - return window.focus(); - }; - if ($.engine !== 'gecko') { - notif.onclose = function() { - return notice.close(); - }; - return notif.onshow = function() { - return setTimeout(function() { - notif.onclose = null; - return notif.close(); - }, 7 * $.SECOND); - }; - } - } - }, - connectionError: function() { - return $.el('span', {innerHTML: "Connection error while posting. [More info]"}); - }, - notifications: [], - cleanNotifications: function() { - var j, len, notification, ref; - ref = QR.notifications; - for (j = 0, len = ref.length; j < len; j++) { - notification = ref[j]; - notification.close(); - } - return QR.notifications = []; - }, - status: function() { - var disabled, status, thread, value; - if (!QR.nodes) { - return; - } - thread = QR.posts[0].thread; - if (thread !== 'new' && g.threads.get(g.BOARD + "." + thread).isDead) { - value = 'Dead'; - disabled = true; - QR.cooldown.auto = false; - } - value = QR.req ? QR.req.progress : QR.cooldown.seconds || value; - status = QR.nodes.status; - status.value = !value ? 'Submit' : QR.cooldown.auto ? "Auto " + value : value; - return status.disabled = disabled || false; - }, - openPost: function() { - var index; - QR.open(); - if (QR.selected.isLocked) { - index = QR.posts.indexOf(QR.selected); - (QR.posts[index + 1] || new QR.post()).select(); - $.addClass(QR.nodes.el, 'dump'); - return QR.cooldown.auto = true; - } - }, - quote: function(e) { - var ancestor, base, caretPos, com, frag, i, insideCode, j, k, l, len, len1, len2, len3, n, node, o, post, postRange, range, ref, ref1, ref2, ref3, ref4, ref5, ref6, root, sel, text, thread, wasOnlyQuotes; - if (e != null) { - e.preventDefault(); - } - if (!QR.postingIsEnabled) { - return; - } - sel = d.getSelection(); - post = Get.postFromNode(this); - root = post.nodes.root; - postRange = new Range(); - postRange.selectNode(root); - text = post.board.ID === g.BOARD.ID ? ">>" + post + "\n" : ">>>/" + post.board + "/" + post + "\n"; - for (i = j = 0, ref = sel.rangeCount; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { - try { - range = sel.getRangeAt(i); - if (range.compareBoundaryPoints(Range.START_TO_START, postRange) < 0) { - range.setStartBefore(root); - } - if (range.compareBoundaryPoints(Range.END_TO_END, postRange) > 0) { - range.setEndAfter(root); - } - if (!range.toString().trim()) { - continue; - } - frag = range.cloneContents(); - ancestor = range.commonAncestorContainer; - if ($.x('ancestor-or-self::*[self::s or contains(@class,"removed-spoiler")]', ancestor)) { - $.prepend(frag, $.tn('[spoiler]')); - $.add(frag, $.tn('[/spoiler]')); - } - if (insideCode = $.x('ancestor-or-self::pre[contains(@class,"prettyprint")]', ancestor)) { - $.prepend(frag, $.tn('[code]')); - $.add(frag, $.tn('[/code]')); - } - ref1 = $$((insideCode ? 'br' : '.prettyprint br'), frag); - for (k = 0, len = ref1.length; k < len; k++) { - node = ref1[k]; - $.replace(node, $.tn('\n')); - } - ref2 = $$('br', frag); - for (l = 0, len1 = ref2.length; l < len1; l++) { - node = ref2[l]; - if (node !== frag.lastChild) { - $.replace(node, $.tn('\n>')); - } - } - if (typeof (base = g.SITE).insertTags === "function") { - base.insertTags(frag); - } - ref3 = $$('.linkify[data-original]', frag); - for (n = 0, len2 = ref3.length; n < len2; n++) { - node = ref3[n]; - $.replace(node, $.tn(node.dataset.original)); - } - ref4 = $$('.embedder', frag); - for (o = 0, len3 = ref4.length; o < len3; o++) { - node = ref4[o]; - if (((ref5 = node.previousSibling) != null ? ref5.nodeValue : void 0) === ' ') { - $.rm(node.previousSibling); - } - $.rm(node); - } - text += ">" + (frag.textContent.trim()) + "\n"; - } catch (error) {} - } - QR.openPost(); - ref6 = QR.nodes, com = ref6.com, thread = ref6.thread; - if (!com.value) { - thread.value = Get.threadFromNode(this); - } - wasOnlyQuotes = QR.selected.isOnlyQuotes(); - caretPos = com.selectionStart; - com.value = com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); - range = caretPos + text.length; - com.setSelectionRange(range, range); - com.focus(); - if (wasOnlyQuotes) { - QR.selected.quotedText = com.value; - } - QR.selected.save(com); - return QR.selected.save(thread); - }, - characterCount: function() { - var count, counter; - counter = QR.nodes.charCount; - count = QR.nodes.com.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; - counter.textContent = count; - counter.hidden = count < QR.max_comment / 2; - return (count > QR.max_comment ? $.addClass : $.rmClass)(counter, 'warning'); - }, - getFile: function() { - var ref; - return $.event('QRFile', (ref = QR.selected) != null ? ref.file : void 0); - }, - drawFile: function(e) { - var el, file, isVideo, ref; - file = (ref = QR.selected) != null ? ref.file : void 0; - if (!(file && /^(image|video)\//.test(file.type))) { - return; - } - isVideo = /^video\//.test(file); - el = $.el((isVideo ? 'video' : 'img')); - $.on(el, 'error', function() { - return QR.openError(); - }); - $.on(el, (isVideo ? 'loadeddata' : 'load'), function() { - e.target.getContext('2d').drawImage(el, 0, 0); - URL.revokeObjectURL(el.src); - return $.event('QRImageDrawn', null, e.target); - }); - return el.src = URL.createObjectURL(file); - }, - openError: function() { - var div; - div = $.el('div'); - $.extend(div, {innerHTML: "Could not open file. [More info]"}); - return QR.error(div); - }, - setFile: function(e) { - var file, name, ref, source; - ref = e.detail, file = ref.file, name = ref.name, source = ref.source; - if (name != null) { - file.name = name; - } - if (source != null) { - file.source = source; - } - QR.open(); - return QR.handleFiles([file]); - }, - 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(); - return QR.handleFiles(e.dataTransfer.files); - }, - paste: function(e) { - var blob, file, file2, item, j, len, ref, score, score2, type; - if (!e.clipboardData.items) { - return; - } - file = null; - score = -1; - ref = e.clipboardData.items; - for (j = 0, len = ref.length; j < len; j++) { - item = ref[j]; - if (!(item.kind === 'file' && (file2 = item.getAsFile()))) { - continue; - } - score2 = 2 * (file2.size <= QR.max_size) + (file2.type === 'image/png'); - if (score2 > score) { - file = file2; - score = score2; - } - } - if (file) { - type = file.type; - blob = new Blob([file], { - type: type - }); - blob.name = Conf['pastedname'] + "." + ($.getOwn(QR.extensionFromType, type) || 'jpg'); - QR.open(); - QR.handleFiles([blob]); - $.addClass(QR.nodes.el, 'dump'); - } - }, - pasteFF: function() { - var arr, blob, bstr, i, images, img, j, k, len, m, pasteArea, ref, src; - pasteArea = QR.nodes.pasteArea; - if (!pasteArea.childNodes.length) { - return; - } - images = $$('img', pasteArea); - $.rmAll(pasteArea); - for (j = 0, len = images.length; j < len; j++) { - img = images[j]; - src = img.src; - if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { - bstr = atob(m[3]); - arr = new Uint8Array(bstr.length); - for (i = k = 0, ref = bstr.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) { - arr[i] = bstr.charCodeAt(i); - } - blob = new Blob([arr], { - type: m[1] - }); - blob.name = Conf['pastedname'] + "." + m[2]; - QR.handleFiles([blob]); - } else if (/^https?:\/\//.test(src)) { - QR.handleUrl(src); - } - } - }, - handleUrl: function(urlDefault) { - QR.open(); - QR.selected.preventAutoPost(); - return CrossOrigin.permission(function() { - var url; - url = prompt('Enter a URL:', urlDefault); - if (url === null) { - return; - } - QR.nodes.fileButton.focus(); - return CrossOrigin.file(url, function(blob) { - if (blob && !/^text\//.test(blob.type)) { - return QR.handleFiles([blob]); - } else { - return QR.error("Can't load file."); - } - }); - }); - }, - handleFiles: function(files) { - var file, j, len; - if (this !== QR) { - files = slice.call(this.files); - this.value = null; - } - if (!files.length) { - return; - } - QR.cleanNotifications(); - for (j = 0, len = files.length; j < len; j++) { - file = files[j]; - QR.handleFile(file, files.length); - } - if (files.length !== 1) { - $.addClass(QR.nodes.el, 'dump'); - } - if (d.activeElement === QR.nodes.fileButton && $.hasClass(QR.nodes.fileSubmit, 'has-file')) { - return QR.nodes.filename.focus(); - } - }, - handleFile: function(file, nfiles) { - var isText, post; - isText = /^text\//.test(file.type); - if (nfiles === 1) { - post = QR.selected; - } else { - post = QR.posts[QR.posts.length - 1]; - if ((isText ? post.com || post.pasting : post.file)) { - post = new QR.post(); - } - } - return post[isText ? 'pasteText' : 'setFile'](file); - }, - openFileInput: function() { - if (QR.nodes.fileButton.disabled) { - return; - } - QR.nodes.fileInput.click(); - return QR.nodes.fileButton.focus(); - }, - generatePostableThreadsList: function() { - var j, len, list, options, ref, thread, val; - if (!QR.nodes) { - return; - } - list = QR.nodes.thread; - options = [list.firstElementChild]; - ref = g.BOARD.threads.keys; - for (j = 0, len = ref.length; j < len; j++) { - thread = ref[j]; - options.push($.el('option', { - value: thread, - textContent: "Thread " + thread - })); - } - val = list.value; - $.rmAll(list); - $.add(list, options); - list.value = val; - if (list.value === val) { - return; - } - list.value = g.VIEW === 'thread' ? g.THREADID : 'new'; - return (g.VIEW === 'thread' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); - }, - dialog: function() { - var classList, config, dialog, event, i, items, name, node, nodes, save, setNode; - QR.nodes = nodes = { - el: dialog = UI.dialog('qr', {innerHTML: "
      ×
      No selected file
      "}) - }; - setNode = function(name, query) { - return nodes[name] = $(query, dialog); - }; - setNode('move', '.move'); - setNode('autohide', '#autohide'); - setNode('close', '.close'); - setNode('thread', 'select'); - setNode('form', 'form'); - setNode('sjisToggle', '#sjis-toggle'); - setNode('texButton', '#tex-preview-button'); - setNode('name', '[data-name=name]'); - setNode('email', '[data-name=email]'); - setNode('sub', '[data-name=sub]'); - setNode('com', '[data-name=com]'); - setNode('charCount', '#char-count'); - setNode('texPreview', '#tex-preview'); - setNode('dumpList', '#dump-list'); - setNode('addPost', '#add-post'); - setNode('oekaki', '.oekaki'); - setNode('drawButton', '#qr-draw-button'); - setNode('fileSubmit', '#file-n-submit'); - setNode('fileButton', '#qr-file-button'); - setNode('noFile', '#qr-no-file'); - setNode('filename', '#qr-filename'); - setNode('spoiler', '#qr-file-spoiler'); - setNode('oekakiButton', '#qr-oekaki-button'); - setNode('fileRM', '#qr-filerm'); - setNode('urlButton', '#url-button'); - setNode('pasteArea', '#paste-area'); - setNode('customCooldown', '#custom-cooldown-button'); - setNode('dumpButton', '#dump-button'); - setNode('status', '[type=submit]'); - setNode('flashTag', '[name=filetag]'); - setNode('fileInput', '[type=file]'); - config = g.BOARD.config; - classList = QR.nodes.el.classList; - classList.toggle('forced-anon', QR.forcedAnon); - classList.toggle('has-spoiler', QR.spoiler); - classList.toggle('has-sjis', !!config.sjis_tags); - classList.toggle('has-math', !!config.math_tags); - classList.toggle('sjis-preview', !!config.sjis_tags && Conf['sjisPreview']); - classList.toggle('show-new-thread-option', Conf['Show New Thread Option in Threads']); - if (parseInt(Conf['customCooldown'], 10) > 0) { - $.addClass(QR.nodes.fileSubmit, 'custom-cooldown'); - $.get('customCooldownEnabled', Conf['customCooldownEnabled'], function(arg) { - var customCooldownEnabled; - customCooldownEnabled = arg.customCooldownEnabled; - QR.setCustomCooldown(customCooldownEnabled); - return $.sync('customCooldownEnabled', QR.setCustomCooldown); - }); - } - QR.flagsInput(); - $.on(nodes.autohide, 'change', QR.toggleHide); - $.on(nodes.close, 'click', QR.close); - $.on(nodes.status, 'click', QR.submit); - $.on(nodes.form, 'submit', QR.submit); - $.on(nodes.sjisToggle, 'click', QR.toggleSJIS); - $.on(nodes.texButton, 'mousedown', QR.texPreviewShow); - $.on(nodes.texButton, 'mouseup', QR.texPreviewHide); - $.on(nodes.addPost, 'click', function() { - return new QR.post(true); - }); - $.on(nodes.drawButton, 'click', QR.oekaki.draw); - $.on(nodes.fileButton, 'click', QR.openFileInput); - $.on(nodes.noFile, 'click', QR.openFileInput); - $.on(nodes.filename, 'focus', function() { - return $.addClass(this.parentNode, 'focus'); - }); - $.on(nodes.filename, 'blur', function() { - return $.rmClass(this.parentNode, 'focus'); - }); - $.on(nodes.spoiler, 'change', function() { - return QR.selected.nodes.spoiler.click(); - }); - $.on(nodes.oekakiButton, 'click', QR.oekaki.button); - $.on(nodes.fileRM, 'click', function() { - return QR.selected.rmFile(); - }); - $.on(nodes.urlButton, 'click', function() { - return QR.handleUrl(''); - }); - $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); - $.on(nodes.dumpButton, 'click', function() { - return nodes.el.classList.toggle('dump'); - }); - $.on(nodes.fileInput, 'change', QR.handleFiles); - window.addEventListener('focus', QR.focus, true); - window.addEventListener('blur', QR.focus, true); - $.on(d, 'click', QR.focus); - if ($.engine === 'gecko' && !window.DataTransferItemList) { - nodes.pasteArea.hidden = false; - } - new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { - childList: true - }); - items = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'flag']; - i = 0; - save = function() { - return QR.selected.save(this); - }; - while (name = items[i++]) { - if (!(node = nodes[name])) { - continue; - } - event = node.nodeName === 'SELECT' ? 'change' : 'input'; - $.on(nodes[name], event, save); - } - if ($.engine === 'gecko' && Conf['Remember QR Size']) { - $.get('QR Size', '', function(item) { - return nodes.com.style.cssText = item['QR Size']; - }); - $.on(nodes.com, 'mouseup', function(e) { - if (e.button !== 0) { - return; - } - return $.set('QR Size', this.style.cssText); - }); - } - QR.generatePostableThreadsList(); - QR.persona.load(); - new QR.post(true); - QR.status(); - QR.cooldown.setup(); - QR.captcha.init(); - $.add(d.body, dialog); - QR.captcha.setup(); - QR.oekaki.setup(); - return $.event('QRDialogCreation', null, dialog); - }, - flags: function() { - var addFlag, ref, select, textContent, value; - select = $.el('select', { - name: 'flag', - className: 'flagSelector' - }); - addFlag = function(value, textContent) { - return $.add(select, $.el('option', { - value: value, - textContent: textContent - })); - }; - addFlag('0', (g.BOARD.config.country_flags ? 'Geographic Location' : 'None')); - ref = g.BOARD.config.board_flags; - for (value in ref) { - textContent = ref[value]; - addFlag(value, textContent); - } - return select; - }, - flagsInput: function() { - var flag, nodes; - nodes = QR.nodes; - if (!nodes) { - return; - } - if (nodes.flag) { - $.rm(nodes.flag); - delete nodes.flag; - } - if (g.BOARD.config.board_flags) { - flag = QR.flags(); - flag.dataset.name = 'flag'; - flag.dataset["default"] = '0'; - nodes.flag = flag; - return $.add(nodes.form, flag); - } - }, - submit: function(e) { - var captcha, cb, err, filetag, force, formData, options, post, ref, thread, threadID; - if (e != null) { - e.preventDefault(); - } - force = e != null ? e.shiftKey : void 0; - if (QR.req) { - QR.abort(); - return; - } - $.forceSync('cooldowns'); - if (QR.cooldown.seconds) { - if (force) { - QR.cooldown.clear(); - } else { - QR.cooldown.auto = !QR.cooldown.auto; - QR.status(); - return; - } - } - post = QR.posts[0]; - delete post.quotedText; - post.forceSave(); - threadID = post.thread; - thread = g.BOARD.threads.get(threadID); - if (g.BOARD.ID === 'f' && threadID === 'new') { - filetag = QR.nodes.flashTag.value; - } - if (threadID === 'new') { - threadID = null; - if (!!g.BOARD.config.require_subject && !post.sub) { - err = 'New threads require a subject.'; - } else if (!(!!g.BOARD.config.text_only || post.file)) { - err = 'No file selected.'; - } - } else if (g.BOARD.threads.get(threadID).isClosed) { - err = 'You can\'t reply to this thread anymore.'; - } else if (!(post.com || post.file)) { - err = 'No comment or file.'; - } else if (post.file && thread.fileLimit) { - err = 'Max limit of image replies has been reached.'; - } - if (g.BOARD.ID === 'r9k' && !((ref = post.com) != null ? ref.match(/[a-z-]/i) : void 0)) { - err || (err = 'Original comment required.'); - } - if (QR.captcha.isEnabled && !(QR.captcha === Captcha.v2 && /\b_ct=/.test(d.cookie) && threadID) && !(err && !force)) { - captcha = QR.captcha.getOne(!!threadID); - if (QR.captcha === Captcha.v2) { - captcha || (captcha = Captcha.cache.request(!!threadID)); - } - if (!captcha) { - err = 'No valid captcha.'; - QR.captcha.setup(!QR.cooldown.auto || d.activeElement === QR.nodes.status); - } - } - QR.cleanNotifications(); - if (err && !force) { - QR.cooldown.auto = false; - QR.status(); - QR.error(err); - return; - } - QR.cooldown.auto = QR.posts.length > 1; - post.lock(); - formData = { - MAX_FILE_SIZE: QR.max_size, - mode: 'regist', - pwd: QR.persona.getPassword(), - resto: threadID, - name: !QR.forcedAnon ? post.name : void 0, - email: post.email, - sub: !(QR.forcedAnon || threadID) ? post.sub : void 0, - com: post.com, - upfile: post.file, - filetag: filetag, - spoiler: post.spoiler, - flag: post.flag - }; - options = { - responseType: 'document', - withCredentials: true, - onloadend: QR.response, - form: $.formData(formData) - }; - if (Conf['Show Upload Progress']) { - options.onprogress = function(e) { - var ref1; - if (this !== ((ref1 = QR.req) != null ? ref1.upload : void 0)) { - return; - } - if (e.loaded < e.total) { - QR.req.progress = (Math.round(e.loaded / e.total * 100)) + "%"; - } else { - QR.req.isUploadFinished = true; - QR.req.progress = '...'; - } - return QR.status(); - }; - } - cb = function(response) { - var key, val; - if (response != null) { - QR.currentCaptcha = response; - if (QR.captcha === Captcha.v2) { - if (response.challenge != null) { - options.form.append('recaptcha_challenge_field', response.challenge); - options.form.append('recaptcha_response_field', response.response); - } else { - options.form.append('g-recaptcha-response', response.response); - } - } else { - for (key in response) { - val = response[key]; - options.form.append(key, val); - } - } - } - QR.req = $.ajax("https://sys." + (location.hostname.split('.')[1]) + ".org/" + g.BOARD + "/post", options); - return QR.req.progress = '...'; - }; - if (typeof captcha === 'function') { - QR.req = { - progress: '...', - abort: function() { - if (QR.captcha === Captcha.v2) { - Captcha.cache.abort(); - } - return cb = null; - } - }; - captcha(function(response) { - if (QR.captcha === Captcha.v2 && Captcha.cache.haveCookie()) { - if (typeof cb === "function") { - cb(); - } - if (response) { - return Captcha.cache.save(response); - } - } else if (response) { - return typeof cb === "function" ? cb(response) : void 0; - } else { - delete QR.req; - post.unlock(); - QR.cooldown.auto = !!Captcha.cache.getCount(); - return QR.status(); - } - }); - } else { - cb(captcha); - } - return QR.status(); - }, - response: function() { - var URL, _, base, connErr, err, h1, isReply, j, lastPostToThread, len, m, mi, open, post, postID, postsCount, ref, ref1, ref2, ref3, seconds, threadID; - if (this !== QR.req) { - return; - } - delete QR.req; - post = QR.posts[0]; - post.unlock(); - if ((err = (ref = this.response) != null ? ref.getElementById('errmsg') : void 0)) { - if ((ref1 = $('a', err)) != null) { - ref1.target = '_blank'; - } - } else if ((connErr = !this.response || this.response.title !== 'Post successful!')) { - err = QR.connectionError(); - if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { - Captcha.cache.save(QR.currentCaptcha); - } - } else if (this.status !== 200) { - err = "Error " + this.statusText + " (" + this.status + ")"; - } - if (!connErr) { - if (typeof (base = QR.captcha).setUsed === "function") { - base.setUsed(); - } - } - delete QR.currentCaptcha; - if (err) { - QR.errorCount = (QR.errorCount || 0) + 1; - if (/captcha|verification/i.test(err.textContent) || connErr) { - if (/mistyped/i.test(err.textContent)) { - err = 'You mistyped the CAPTCHA, or the CAPTCHA malfunctioned.'; - } else if (/expired/i.test(err.textContent)) { - err = 'This CAPTCHA is no longer valid because it has expired.'; - } - if (QR.errorCount >= 5) { - QR.cooldown.auto = false; - } else { - QR.cooldown.auto = QR.captcha.isEnabled || connErr; - QR.cooldown.addDelay(post, 2); - } - } else if (err.textContent && (m = err.textContent.match(/\d+\s+(?:minute|second)/gi)) && !/duplicate|hour/i.test(err.textContent)) { - QR.cooldown.auto = !/have\s+been\s+muted/i.test(err.textContent); - seconds = 0; - for (j = 0, len = m.length; j < len; j++) { - mi = m[j]; - seconds += (/minute/i.test(mi) ? 60 : 1) * (+mi.match(/\d+/)[0]); - } - if (/muted/i.test(err.textContent)) { - QR.cooldown.addMute(seconds); - } else { - QR.cooldown.addDelay(post, seconds); - } - } else { - QR.cooldown.auto = false; - } - QR.captcha.setup(QR.cooldown.auto && ((ref2 = d.activeElement) === QR.nodes.status || ref2 === d.body)); - QR.status(); - QR.error(err); - return; - } - delete QR.errorCount; - h1 = $('h1', this.response); - ref3 = h1.nextSibling.textContent.match(/thread:(\d+),no:(\d+)/), _ = ref3[0], threadID = ref3[1], postID = ref3[2]; - postID = +postID; - threadID = +threadID || postID; - isReply = threadID !== postID; - $.event('QRPostSuccessful', { - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID - }); - $.event('QRPostSuccessful_', { - boardID: g.BOARD.ID, - threadID: threadID, - postID: postID - }); - postsCount = QR.posts.length - 1; - QR.cooldown.auto = postsCount && isReply; - lastPostToThread = !((function() { - var k, len1, p, ref4; - ref4 = QR.posts.slice(1); - for (k = 0, len1 = ref4.length; k < len1; k++) { - p = ref4[k]; - if (p.thread === post.thread) { - return true; - } - } - })()); - if (postsCount) { - post.rm(); - QR.captcha.setup(d.activeElement === QR.nodes.status); - } else if (Conf['Persistent QR']) { - post.rm(); - if (Conf['Auto Hide QR']) { - QR.hide(); - } else { - QR.blur(); - } - } else { - QR.close(); - } - QR.cleanNotifications(); - if (Conf['Posting Success Notifications']) { - QR.notifications.push(new Notice('success', h1.textContent, 5)); - } - QR.cooldown.add(threadID, postID); - URL = threadID === postID ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID : threadID !== g.THREADID && lastPostToThread && Conf['Open Post in New Tab'] ? window.location.origin + "/" + g.BOARD + "/thread/" + threadID + "#p" + postID : void 0; - if (URL) { - open = Conf['Open Post in New Tab'] || postsCount ? function() { - return $.open(URL); - } : function() { - return location.href = URL; - }; - if (threadID === postID) { - QR.waitForThread(URL, open); - } else { - open(); - } - } - return QR.status(); - }, - waitForThread: function(url, cb) { - var attempts, check; - attempts = 0; - check = function() { - return $.ajax(url, { - onloadend: function() { - attempts++; - if (attempts >= 6 || this.status === 200) { - return cb(); - } else { - return setTimeout(check, attempts * $.SECOND); - } - }, - responseType: 'text', - type: 'HEAD' - }); - }; - return check(); - }, - abort: function() { - var oldReq; - if ((oldReq = QR.req) && !QR.req.isUploadFinished) { - delete QR.req; - oldReq.abort(); - if (QR.captcha === Captcha.v2 && QR.currentCaptcha) { - Captcha.cache.save(QR.currentCaptcha); - } - delete QR.currentCaptcha; - QR.posts[0].unlock(); - QR.cooldown.auto = false; - QR.notifications.push(new Notice('info', 'QR upload aborted.', 5)); - } - return QR.status(); - } - }; - - return QR; - -}).call(this); - -(function() { - QR.cooldown = { - seconds: 0, - delays: { - deletion: 60 - }, - init: function() { - if (!Conf['Quick Reply']) { - return; - } - this.data = Conf['cooldowns']; - this.changes = $.dict(); - return $.sync('cooldowns', this.sync); - }, - setup: function() { - var delay, ref, type; - $.extend(QR.cooldown.delays, g.BOARD.cooldowns()); - QR.cooldown.maxDelay = 0; - ref = QR.cooldown.delays; - for (type in ref) { - delay = ref[type]; - if (type !== 'thread' && type !== 'thread_global') { - QR.cooldown.maxDelay = Math.max(QR.cooldown.maxDelay, delay); - } - } - QR.cooldown.isSetup = true; - return QR.cooldown.start(); - }, - start: function() { - var data; - data = QR.cooldown.data; - if (!(Conf['Cooldown'] && QR.cooldown.isSetup && !QR.cooldown.isCounting && Object.keys(data[g.BOARD.ID] || {}).length + Object.keys(data.global || {}).length > 0)) { - return; - } - QR.cooldown.isCounting = true; - return QR.cooldown.count(); - }, - sync: function(data) { - QR.cooldown.data = data || $.dict(); - return QR.cooldown.start(); - }, - add: function(threadID, postID) { - var boardID, start; - if (!Conf['Cooldown']) { - return; - } - start = Date.now(); - boardID = g.BOARD.ID; - QR.cooldown.set(boardID, start, { - threadID: threadID, - postID: postID - }); - if (threadID === postID) { - QR.cooldown.set('global', start, { - boardID: boardID, - threadID: threadID, - postID: postID - }); - } - QR.cooldown.save(); - return QR.cooldown.start(); - }, - addDelay: function(post, delay) { - var cooldown; - if (!Conf['Cooldown']) { - return; - } - cooldown = QR.cooldown.categorize(post); - cooldown.delay = delay; - QR.cooldown.set(g.BOARD.ID, Date.now(), cooldown); - QR.cooldown.save(); - return QR.cooldown.start(); - }, - addMute: function(delay) { - if (!Conf['Cooldown']) { - return; - } - QR.cooldown.set(g.BOARD.ID, Date.now(), { - type: 'mute', - delay: delay - }); - QR.cooldown.save(); - return QR.cooldown.start(); - }, - "delete": function(post) { - var base, cooldown, cooldowns, id, name; - if (!QR.cooldown.data) { - return; - } - cooldowns = ((base = QR.cooldown.data)[name = post.board.ID] || (base[name] = $.dict())); - for (id in cooldowns) { - cooldown = cooldowns[id]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - QR.cooldown.set(post.board.ID, id, null); - } - } - return QR.cooldown.save(); - }, - secondsDeletion: function(post) { - var cooldown, cooldowns, seconds, start; - if (!(QR.cooldown.data && Conf['Cooldown'])) { - return 0; - } - cooldowns = QR.cooldown.data[post.board.ID] || $.dict(); - for (start in cooldowns) { - cooldown = cooldowns[start]; - if ((cooldown.delay == null) && cooldown.threadID === post.thread.ID && cooldown.postID === post.ID) { - seconds = QR.cooldown.delays.deletion - Math.floor((Date.now() - start) / $.SECOND); - return Math.max(seconds, 0); - } - } - return 0; - }, - categorize: function(post) { - if (post.thread === 'new') { - return { - type: 'thread' - }; - } else { - return { - type: !!post.file ? 'image' : 'reply', - threadID: +post.thread - }; - } - }, - mergeChange: function(data, scope, id, value) { - if (value) { - return (data[scope] || (data[scope] = $.dict()))[id] = value; - } else if (scope in data) { - delete data[scope][id]; - if (Object.keys(data[scope]).length === 0) { - return delete data[scope]; - } - } - }, - set: function(scope, id, value) { - var base; - QR.cooldown.mergeChange(QR.cooldown.data, scope, id, value); - return ((base = QR.cooldown.changes)[scope] || (base[scope] = $.dict()))[id] = value; - }, - save: function() { - var changes; - changes = QR.cooldown.changes; - if (!Object.keys(changes).length) { - return; - } - return $.get('cooldowns', $.dict(), function(arg) { - var cooldowns, id, ref, scope, value; - cooldowns = arg.cooldowns; - for (scope in QR.cooldown.changes) { - ref = QR.cooldown.changes[scope]; - for (id in ref) { - value = ref[id]; - QR.cooldown.mergeChange(cooldowns, scope, id, value); - } - QR.cooldown.data = cooldowns; - } - return $.set('cooldowns', cooldowns, function() { - return QR.cooldown.changes = $.dict(); - }); - }); - }, - clear: function() { - QR.cooldown.data = $.dict(); - QR.cooldown.changes = $.dict(); - QR.cooldown.auto = false; - QR.cooldown.update(); - return $.queueTask($["delete"], 'cooldowns'); - }, - update: function() { - var base, cooldown, cooldowns, elapsed, i, len, maxDelay, nCooldowns, now, ref, ref1, save, scope, seconds, start, suffix, threadID, type, update; - if (!QR.cooldown.isCounting) { - return; - } - save = false; - nCooldowns = 0; - now = Date.now(); - ref = QR.cooldown.categorize(QR.posts[0]), type = ref.type, threadID = ref.threadID; - seconds = 0; - if (Conf['Cooldown']) { - ref1 = [g.BOARD.ID, 'global']; - for (i = 0, len = ref1.length; i < len; i++) { - scope = ref1[i]; - cooldowns = ((base = QR.cooldown.data)[scope] || (base[scope] = $.dict())); - for (start in cooldowns) { - cooldown = cooldowns[start]; - start = +start; - elapsed = Math.floor((now - start) / $.SECOND); - if (elapsed < 0) { - QR.cooldown.set(scope, start, null); - save = true; - continue; - } - if (cooldown.delay != null) { - if (cooldown.delay <= elapsed) { - QR.cooldown.set(scope, start, null); - save = true; - } else if ((cooldown.type === type && cooldown.threadID === threadID) || cooldown.type === 'mute') { - seconds = Math.max(seconds, cooldown.delay - elapsed); - } - continue; - } - maxDelay = cooldown.threadID !== cooldown.postID ? QR.cooldown.maxDelay : QR.cooldown.delays[scope === 'global' ? 'thread_global' : 'thread']; - if (QR.cooldown.customCooldown) { - maxDelay = Math.max(maxDelay, parseInt(Conf['customCooldown'], 10)); - } - if (maxDelay <= elapsed) { - QR.cooldown.set(scope, start, null); - save = true; - continue; - } - if ((type === 'thread') === (cooldown.threadID === cooldown.postID) && cooldown.boardID !== g.BOARD.ID) { - suffix = scope === 'global' ? '_global' : ''; - seconds = Math.max(seconds, QR.cooldown.delays[type + suffix] - elapsed); - if (QR.cooldown.customCooldown) { - seconds = Math.max(seconds, parseInt(Conf['customCooldown'], 10) - elapsed); - } - } - } - nCooldowns += Object.keys(cooldowns).length; - } - } - if (save) { - QR.cooldown.save; - } - if (nCooldowns) { - clearTimeout(QR.cooldown.timeout); - QR.cooldown.timeout = setTimeout(QR.cooldown.count, $.SECOND); - } else { - delete QR.cooldown.isCounting; - } - update = seconds !== QR.cooldown.seconds; - QR.cooldown.seconds = seconds; - if (update) { - return QR.status(); - } - }, - count: function() { - QR.cooldown.update(); - if (QR.cooldown.seconds === 0 && QR.cooldown.auto && !QR.req) { - return QR.submit(); - } - } - }; - -}).call(this); - -(function() { - QR.oekaki = { - menu: { - init: function() { - var a, ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && Conf['Menu'] && Conf['Edit Link'] && Conf['Quick Reply'])) { - return; - } - a = $.el('a', { - className: 'edit-link', - href: 'javascript:;', - textContent: 'Edit image' - }); - $.on(a, 'click', this.editFile); - return Menu.menu.addEntry({ - el: a, - order: 90, - open: function(post) { - var file; - QR.oekaki.menu.post = post; - file = post.file; - return QR.postingIsEnabled && !!file && (file.isImage || file.isVideo); - } - }); - }, - editFile: function() { - var currentTime, isVideo, post, ref; - post = QR.oekaki.menu.post; - QR.quote.call(post.nodes.post); - isVideo = post.file.isVideo; - currentTime = ((ref = post.file.fullImage) != null ? ref.currentTime : void 0) || 0; - return CrossOrigin.file(post.file.url, function(blob) { - var video; - if (!blob) { - return QR.error("Can't load file."); - } else if (isVideo) { - video = $.el('video'); - $.on(video, 'loadedmetadata', function() { - $.on(video, 'seeked', function() { - var canvas; - canvas = $.el('canvas', { - width: video.videoWidth, - height: video.videoHeight - }); - canvas.getContext('2d').drawImage(video, 0, 0); - return canvas.toBlob(function(snapshot) { - snapshot.name = post.file.name.replace(/\.\w+$/, '') + '.png'; - QR.handleFiles([snapshot]); - return QR.oekaki.edit(); - }); - }); - return video.currentTime = currentTime; - }); - $.on(video, 'error', function() { - return QR.openError(); - }); - return video.src = URL.createObjectURL(blob); - } else { - blob.name = post.file.name; - QR.handleFiles([blob]); - return QR.oekaki.edit(); - } - }); - } - }, - setup: function() { - return $.global(function() { - var FCX; - FCX = window.FCX; - FCX.oekakiCB = function() { - return window.Tegaki.flatten().toBlob(function(file) { - var source; - source = "oekaki-" + (Date.now()); - FCX.oekakiLatest = source; - return document.dispatchEvent(new CustomEvent('QRSetFile', { - bubbles: true, - detail: { - file: file, - name: FCX.oekakiName, - source: source - } - })); - }); - }; - if (window.Tegaki) { - return document.querySelector('#qr .oekaki').hidden = false; - } - }); - }, - load: function(cb) { - var n, onload, script, style; - if ($('script[src^="//s.4cdn.org/js/tegaki"]', d.head)) { - return cb(); - } else { - style = $.el('link', { - rel: 'stylesheet', - href: "//s.4cdn.org/css/tegaki." + (Date.now()) + ".css" - }); - script = $.el('script', { - src: "//s.4cdn.org/js/tegaki.min." + (Date.now()) + ".js" - }); - n = 0; - onload = function() { - if (++n === 2) { - return cb(); - } - }; - $.on(style, 'load', onload); - $.on(script, 'load', onload); - return $.add(d.head, [style, script]); - } - }, - draw: function() { - return $.global(function() { - var FCX, Tegaki; - Tegaki = window.Tegaki, FCX = window.FCX; - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = 'tegaki.png'; - return Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: +document.querySelector('#qr [name=oekaki-width]').value, - height: +document.querySelector('#qr [name=oekaki-height]').value, - bgColor: document.querySelector('#qr [name=oekaki-bg]').checked ? document.querySelector('#qr [name=oekaki-bgcolor]').value : 'transparent' - }); - }); - }, - button: function() { - if (QR.selected.file) { - return QR.oekaki.edit(); - } else { - return QR.oekaki.toggle(); - } - }, - edit: function() { - return QR.oekaki.load(function() { - return $.global(function() { - var FCX, Tegaki, cb, error, name, source; - Tegaki = window.Tegaki, FCX = window.FCX; - name = document.getElementById('qr-filename').value.replace(/\.\w+$/, '') + '.png'; - source = document.getElementById('file-n-submit').dataset.source; - error = function(content) { - return document.dispatchEvent(new CustomEvent('CreateNotification', { - bubbles: true, - detail: { - type: 'warning', - content: content, - lifetime: 20 - } - })); - }; - cb = function(e) { - var canvas, selected; - if (e) { - this.removeEventListener('QRMetadata', cb, false); - } - selected = document.getElementById('selected'); - if (!(selected != null ? selected.dataset.type : void 0)) { - return error('No file to edit.'); - } - if (!/^(image|video)\//.test(selected.dataset.type)) { - return error('Not an image.'); - } - if (!selected.dataset.height) { - return error('Metadata not available.'); - } - if (selected.dataset.height === 'loading') { - selected.addEventListener('QRMetadata', cb, false); - return; - } - if (Tegaki.bg) { - Tegaki.destroy(); - } - FCX.oekakiName = name; - Tegaki.open({ - onDone: FCX.oekakiCB, - onCancel: function() { - return Tegaki.bgColor = '#ffffff'; - }, - width: +selected.dataset.width, - height: +selected.dataset.height, - bgColor: 'transparent' - }); - canvas = document.createElement('canvas'); - canvas.width = canvas.naturalWidth = +selected.dataset.width; - canvas.height = canvas.naturalHeight = +selected.dataset.height; - canvas.hidden = true; - document.body.appendChild(canvas); - canvas.addEventListener('QRImageDrawn', function() { - this.remove(); - return Tegaki.onOpenImageLoaded.call(this); - }, false); - return canvas.dispatchEvent(new CustomEvent('QRDrawFile', { - bubbles: true - })); - }; - if (Tegaki.bg && Tegaki.onDoneCb === FCX.oekakiCB && source === FCX.oekakiLatest) { - FCX.oekakiName = name; - return Tegaki.resume(); - } else { - return cb(); - } - }); - }); - }, - toggle: function() { - return QR.oekaki.load(function() { - return QR.nodes.oekaki.hidden = !QR.nodes.oekaki.hidden; - }); - } - }; - -}).call(this); - -(function() { - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - QR.persona = { - always: {}, - types: { - name: [], - email: [], - sub: [] - }, - init: function() { - var i, item, len, ref; - if (!(Conf['Quick Reply'] || (Conf['Menu'] && Conf['Delete Link']))) { - return; - } - ref = Conf['QR.personas'].split('\n'); - for (i = 0, len = ref.length; i < len; i++) { - item = ref[i]; - QR.persona.parseItem(item.trim()); - } - }, - parseItem: function(item) { - var boards, match, ref, ref1, ref2, type, val; - if (item[0] === '#') { - return; - } - if (!(match = item.match(/(name|options|email|subject|password):"(.*)"/i))) { - return; - } - ref = match, match = ref[0], type = ref[1], val = ref[2]; - item = item.replace(match, ''); - boards = ((ref1 = item.match(/boards:([^;]+)/i)) != null ? ref1[1].toLowerCase() : void 0) || 'global'; - if (boards !== 'global' && (ref2 = g.BOARD.ID, indexOf.call(boards.split(','), ref2) < 0)) { - return; - } - if (type === 'password') { - QR.persona.pwd = val; - return; - } - if (type === 'options') { - type = 'email'; - } - if (type === 'subject') { - type = 'sub'; - } - if (/always/i.test(item)) { - QR.persona.always[type] = val; - } - if (indexOf.call(QR.persona.types[type], val) < 0) { - return QR.persona.types[type].push(val); - } - }, - load: function() { - var arr, i, len, list, ref, type, val; - ref = QR.persona.types; - for (type in ref) { - arr = ref[type]; - list = $("#list-" + type, QR.nodes.el); - for (i = 0, len = arr.length; i < len; i++) { - val = arr[i]; - if (val) { - $.add(list, $.el('option', { - textContent: val - })); - } - } - } - }, - getPassword: function() { - var m; - if (QR.persona.pwd != null) { - return QR.persona.pwd; - } else if ((m = d.cookie.match(/4chan_pass=([^;]+)/))) { - return decodeURIComponent(m[1]); - } else { - return ''; - } - }, - get: function(cb) { - return $.get('QR.persona', {}, function(arg) { - var persona; - persona = arg['QR.persona']; - return cb(persona); - }); - }, - set: function(post) { - return $.get('QR.persona', {}, function(arg) { - var persona; - persona = arg['QR.persona']; - persona = { - name: post.name, - flag: post.flag - }; - return $.set('QR.persona', persona); - }); - } - }; - -}).call(this); - -(function() { - var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - QR.post = (function() { - function _Class(select) { - this.select = bind(this.select, this); - var el, event, i, j, label, len, len1, prev, ref, ref1; - el = $.el('a', { - className: 'qr-preview', - draggable: true, - href: 'javascript:;' - }); - $.extend(el, {innerHTML: ""}); - this.nodes = { - el: el, - rm: el.firstChild, - spoiler: $('.qr-preview-spoiler input', el), - span: el.lastChild - }; - $.on(el, 'click', this.select); - $.on(this.nodes.rm, 'click', (function(_this) { - return function(e) { - e.stopPropagation(); - return _this.rm(); - }; - })(this)); - $.on(this.nodes.spoiler, 'change', (function(_this) { - return function(e) { - _this.spoiler = e.target.checked; - if (_this === QR.selected) { - QR.nodes.spoiler.checked = _this.spoiler; - } - return _this.preventAutoPost(); - }; - })(this)); - ref = $$('label', el); - for (i = 0, len = ref.length; i < len; i++) { - label = ref[i]; - $.on(label, 'click', function(e) { - return e.stopPropagation(); - }); - } - $.add(QR.nodes.dumpList, el); - ref1 = ['dragStart', 'dragEnter', 'dragLeave', 'dragOver', 'dragEnd', 'drop']; - for (j = 0, len1 = ref1.length; j < len1; j++) { - event = ref1[j]; - $.on(el, event.toLowerCase(), this[event]); - } - this.thread = g.VIEW === 'thread' ? g.THREADID : 'new'; - prev = QR.posts[QR.posts.length - 1]; - QR.posts.push(this); - this.nodes.spoiler.checked = this.spoiler = prev && Conf['Remember Spoiler'] ? prev.spoiler : false; - QR.persona.get((function(_this) { - return function(persona) { - _this.name = 'name' in QR.persona.always ? QR.persona.always.name : prev ? prev.name : persona.name; - _this.email = 'email' in QR.persona.always ? QR.persona.always.email : ''; - _this.sub = 'sub' in QR.persona.always ? QR.persona.always.sub : ''; - if (QR.nodes.flag) { - _this.flag = prev ? prev.flag : persona.flag && persona.flag in g.BOARD.config.board_flags ? persona.flag : void 0; - } - if (QR.selected === _this) { - return _this.load(); - } - }; - })(this)); - if (select) { - this.select(); - } - this.unlock(); - QR.captcha.moreNeeded(); - } - - _Class.prototype.rm = function() { - var base, index; - this["delete"](); - index = QR.posts.indexOf(this); - if (QR.posts.length === 1) { - new QR.post(true); - $.rmClass(QR.nodes.el, 'dump'); - } else if (this === QR.selected) { - (QR.posts[index - 1] || QR.posts[index + 1]).select(); - } - QR.posts.splice(index, 1); - QR.status(); - return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; - }; - - _Class.prototype["delete"] = function() { - $.rm(this.nodes.el); - URL.revokeObjectURL(this.URL); - return this.dismissErrors(); - }; - - _Class.prototype.lock = function(lock) { - var i, len, name, node, ref; - if (lock == null) { - lock = true; - } - this.isLocked = lock; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'fileButton', 'filename', 'spoiler', 'flag']; - for (i = 0, len = ref.length; i < len; i++) { - name = ref[i]; - if (node = QR.nodes[name]) { - node.disabled = lock; - } - } - this.nodes.rm.style.visibility = lock ? 'hidden' : ''; - this.nodes.spoiler.disabled = lock; - return this.nodes.el.draggable = !lock; - }; - - _Class.prototype.unlock = function() { - return this.lock(false); - }; - - _Class.prototype.select = function() { - var rectEl, rectList; - if (QR.selected) { - QR.selected.nodes.el.removeAttribute('id'); - QR.selected.forceSave(); - } - QR.selected = this; - this.lock(this.isLocked); - this.nodes.el.id = 'selected'; - rectEl = this.nodes.el.getBoundingClientRect(); - rectList = this.nodes.el.parentNode.getBoundingClientRect(); - this.nodes.el.parentNode.scrollLeft += rectEl.left + rectEl.width / 2 - rectList.left - rectList.width / 2; - return this.load(); - }; - - _Class.prototype.load = function() { - var i, len, name, node, ref; - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'flag']; - for (i = 0, len = ref.length; i < len; i++) { - name = ref[i]; - if (!(node = QR.nodes[name])) { - continue; - } - node.value = this[name] || node.dataset["default"] || ''; - } - (this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); - this.showFileData(); - return QR.characterCount(); - }; - - _Class.prototype.save = function(input, forced) { - var base, name, prev; - if (input.type === 'checkbox') { - this.spoiler = input.checked; - return; - } - name = input.dataset.name; - if (name !== 'thread' && name !== 'name' && name !== 'email' && name !== 'sub' && name !== 'com' && name !== 'filename' && name !== 'flag') { - return; - } - prev = this[name] || input.dataset["default"] || null; - this[name] = input.value || input.dataset["default"] || null; - switch (name) { - case 'thread': - (this.thread !== 'new' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); - QR.status(); - if (typeof (base = QR.captcha).updateThread === "function") { - base.updateThread(); - } - break; - case 'com': - this.updateComment(); - break; - case 'filename': - if (!this.file) { - return; - } - this.saveFilename(); - this.updateFilename(); - break; - case 'name': - case 'flag': - if (this[name] !== prev) { - QR.persona.set(this); - } - } - if (!forced) { - return this.preventAutoPost(); - } - }; - - _Class.prototype.forceSave = function() { - var i, len, name, node, ref; - if (this !== QR.selected) { - return; - } - ref = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'spoiler', 'flag']; - for (i = 0, len = ref.length; i < len; i++) { - name = ref[i]; - if (!(node = QR.nodes[name])) { - continue; - } - this.save(node, true); - } - }; - - _Class.prototype.preventAutoPost = function() { - if (QR.cooldown.auto && this === QR.posts[0]) { - QR.cooldown.update(); - if (QR.cooldown.seconds <= 5) { - return QR.cooldown.auto = false; - } - } - }; - - _Class.prototype.setComment = function(com) { - this.com = com || null; - if (this === QR.selected) { - QR.nodes.com.value = this.com; - } - return this.updateComment(); - }; - - _Class.prototype.updateComment = function() { - if (this === QR.selected) { - QR.characterCount(); - } - this.nodes.span.textContent = this.com; - QR.captcha.moreNeeded(); - if (QR.captcha === Captcha.v2) { - return Captcha.cache.prerequest(); - } - }; - - _Class.prototype.isOnlyQuotes = function() { - return (this.com || '').trim() === (this.quotedText || '').trim(); - }; - - _Class.rmErrored = function(e) { - var error, errors, i, j, len, post, ref; - e.stopPropagation(); - ref = QR.posts; - for (i = ref.length - 1; i >= 0; i += -1) { - post = ref[i]; - if (errors = post.errors) { - for (j = 0, len = errors.length; j < len; j++) { - error = errors[j]; - if (!(doc.contains(error))) { - continue; - } - post.rm(); - break; - } - } - } - }; - - _Class.prototype.error = function(className, message, link) { - var div, ref, rm, rmAll; - div = $.el('div', { - className: className - }); - $.extend(div, {innerHTML: E(message) + ((link) ? " [More info]" : "") + "
      [delete post] [delete all]"}); - (this.errors || (this.errors = [])).push(div); - ref = $$('a', div), rm = ref[0], rmAll = ref[1]; - $.on(div, 'click', (function(_this) { - return function() { - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.select(); - } - }; - })(this)); - $.on(rm, 'click', (function(_this) { - return function(e) { - e.stopPropagation(); - if (indexOf.call(QR.posts, _this) >= 0) { - return _this.rm(); - } - }; - })(this)); - $.on(rmAll, 'click', QR.post.rmErrored); - return QR.error(div, true); - }; - - _Class.prototype.fileError = function(message, link) { - return this.error('file-error', this.filename + ": " + message, link); - }; - - _Class.prototype.dismissErrors = function(test) { - var error, i, len, ref; - if (test == null) { - test = function() { - return true; - }; - } - if (this.errors) { - ref = this.errors; - for (i = 0, len = ref.length; i < len; i++) { - error = ref[i]; - if (doc.contains(error) && test(error)) { - error.parentNode.previousElementSibling.click(); - } - } - } - }; - - _Class.prototype.setFile = function(file1) { - var ext, ref; - this.file = file1; - if (Conf['Randomize Filename'] && g.BOARD.ID !== 'f') { - this.filename = "" + (Date.now() * 1000 - Math.floor(Math.random() * 365 * $.DAY * 1000)); - if (ext = this.file.name.match(QR.validExtension)) { - this.filename += ext[0]; - } - } else { - this.filename = this.file.name; - } - this.filesize = $.bytesToString(this.file.size); - this.checkSize(); - $.addClass(this.nodes.el, 'has-file'); - QR.captcha.moreNeeded(); - URL.revokeObjectURL(this.URL); - this.saveFilename(); - if (this === QR.selected) { - this.showFileData(); - } else { - this.updateFilename(); - } - this.rmMetadata(); - this.nodes.el.dataset.type = this.file.type; - this.nodes.el.style.backgroundImage = ''; - if (ref = this.file.type, indexOf.call(QR.mimeTypes, ref) < 0) { - this.fileError('Unsupported file type.'); - } else if (/^(image|video)\//.test(this.file.type)) { - this.readFile(); - } - return this.preventAutoPost(); - }; - - _Class.prototype.checkSize = function() { - var max; - max = QR.max_size; - if (/^video\//.test(this.file.type)) { - max = Math.min(max, QR.max_size_video); - } - if (this.file.size > max) { - return this.fileError("File too large (file: " + this.filesize + ", max: " + ($.bytesToString(max)) + ")."); - } - }; - - _Class.prototype.readFile = function() { - var el, event, isVideo, onerror, onload; - isVideo = /^video\//.test(this.file.type); - el = $.el(isVideo ? 'video' : 'img'); - if (isVideo && !el.canPlayType(this.file.type)) { - return; - } - event = isVideo ? 'loadeddata' : 'load'; - onload = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.checkDimensions(el); - _this.setThumbnail(el); - return $.event('QRMetadata', null, _this.nodes.el); - }; - })(this); - onerror = (function(_this) { - return function() { - $.off(el, event, onload); - $.off(el, 'error', onerror); - _this.fileError("Corrupt " + (isVideo ? 'video' : 'image') + " or error reading metadata.", 'https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions#error-reading-metadata'); - URL.revokeObjectURL(el.src); - _this.nodes.el.removeAttribute('data-height'); - return $.event('QRMetadata', null, _this.nodes.el); - }; - })(this); - this.nodes.el.dataset.height = 'loading'; - $.on(el, event, onload); - $.on(el, 'error', onerror); - return el.src = URL.createObjectURL(this.file); - }; - - _Class.prototype.checkDimensions = function(el) { - var duration, height, max_height, max_width, videoHeight, videoWidth, width; - if (el.tagName === 'IMG') { - height = el.height, width = el.width; - this.nodes.el.dataset.height = height; - this.nodes.el.dataset.width = width; - if (height > QR.max_height || width > QR.max_width) { - this.fileError("Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - } - if (height < QR.min_height || width < QR.min_width) { - return this.fileError("Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - } else { - videoHeight = el.videoHeight, videoWidth = el.videoWidth, duration = el.duration; - this.nodes.el.dataset.height = videoHeight; - this.nodes.el.dataset.width = videoWidth; - this.nodes.el.dataset.duration = duration; - max_height = Math.min(QR.max_height, QR.max_height_video); - max_width = Math.min(QR.max_width, QR.max_width_video); - if (videoHeight > max_height || videoWidth > max_width) { - this.fileError("Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - } - if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - this.fileError("Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - } - if (!isFinite(duration)) { - this.fileError('Video lacks duration metadata (try remuxing)'); - } else if (duration > QR.max_duration_video) { - this.fileError("Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - } - if (BoardConfig.noAudio(g.BOARD.ID) && $.hasAudio(el)) { - return this.fileError('Audio not allowed'); - } - } - }; - - _Class.prototype.setThumbnail = function(el) { - var cv, height, isVideo, s, width; - isVideo = el.tagName === 'VIDEO'; - s = 90 * 2 * window.devicePixelRatio; - if (this.file.type === 'image/gif') { - s *= 3; - } - if (isVideo) { - height = el.videoHeight; - width = el.videoWidth; - } else { - height = el.height, width = el.width; - if (height < s || width < s) { - this.URL = el.src; - this.nodes.el.style.backgroundImage = "url(" + this.URL + ")"; - return; - } - } - if (height <= width) { - width = s / height * width; - height = s; - } else { - height = s / width * height; - width = s; - } - cv = $.el('canvas'); - cv.height = height; - cv.width = width; - cv.getContext('2d').drawImage(el, 0, 0, width, height); - URL.revokeObjectURL(el.src); - return cv.toBlob((function(_this) { - return function(blob) { - _this.URL = URL.createObjectURL(blob); - return _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; - }; - })(this)); - }; - - _Class.prototype.rmFile = function() { - if (this.isLocked) { - return; - } - delete this.file; - delete this.filename; - delete this.filesize; - this.nodes.el.removeAttribute('title'); - QR.nodes.filename.removeAttribute('title'); - this.rmMetadata(); - this.nodes.el.style.backgroundImage = ''; - $.rmClass(this.nodes.el, 'has-file'); - this.showFileData(); - URL.revokeObjectURL(this.URL); - this.dismissErrors(function(error) { - return $.hasClass(error, 'file-error'); - }); - return this.preventAutoPost(); - }; - - _Class.prototype.rmMetadata = function() { - var attr, i, len, ref; - ref = ['type', 'height', 'width', 'duration']; - for (i = 0, len = ref.length; i < len; i++) { - attr = ref[i]; - this.nodes.el.removeAttribute("data-" + attr); - } - }; - - _Class.prototype.saveFilename = function() { - this.file.newName = (this.filename || '').replace(/[\/\\]/g, '-'); - if (!QR.validExtension.test(this.filename)) { - return this.file.newName += "." + ($.getOwn(QR.extensionFromType, this.file.type) || 'jpg'); - } - }; - - _Class.prototype.updateFilename = function() { - var long; - long = this.filename + " (" + this.filesize + ")"; - this.nodes.el.title = long; - if (this !== QR.selected) { - return; - } - return QR.nodes.filename.title = long; - }; - - _Class.prototype.showFileData = function() { - var ref; - if (this.file) { - this.updateFilename(); - QR.nodes.filename.value = this.filename; - $.addClass(QR.nodes.oekaki, 'has-file'); - $.addClass(QR.nodes.fileSubmit, 'has-file'); - } else { - $.rmClass(QR.nodes.oekaki, 'has-file'); - $.rmClass(QR.nodes.fileSubmit, 'has-file'); - } - if (((ref = this.file) != null ? ref.source : void 0) != null) { - QR.nodes.fileSubmit.dataset.source = this.file.source; - } else { - QR.nodes.fileSubmit.removeAttribute('data-source'); - } - return QR.nodes.spoiler.checked = this.spoiler; - }; - - _Class.prototype.pasteText = function(file) { - var reader; - this.pasting = true; - this.preventAutoPost(); - reader = new FileReader(); - reader.onload = (function(_this) { - return function(e) { - var result; - result = e.target.result; - _this.setComment((_this.com ? _this.com + "\n" + result : result)); - return delete _this.pasting; - }; - })(this); - return reader.readAsText(file); - }; - - _Class.prototype.dragStart = function(e) { - var left, ref, top; - ref = this.getBoundingClientRect(), left = ref.left, top = ref.top; - e.dataTransfer.setDragImage(this, e.clientX - left, e.clientY - top); - return $.addClass(this, 'drag'); - }; - - _Class.prototype.dragEnd = function() { - return $.rmClass(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 base, el, index, newIndex, oldIndex, post; - $.rmClass(this, 'over'); - if (!this.draggable) { - return; - } - el = $('.drag', this.parentNode); - index = function(el) { - return slice.call(el.parentNode.children).indexOf(el); - }; - oldIndex = index(el); - newIndex = index(this); - if (QR.posts[oldIndex].isLocked || QR.posts[newIndex].isLocked) { - return; - } - (oldIndex < newIndex ? $.after : $.before)(this, el); - post = QR.posts.splice(oldIndex, 1)[0]; - QR.posts.splice(newIndex, 0, post); - QR.status(); - return typeof (base = QR.captcha).updateThread === "function" ? base.updateThread() : void 0; - }; - - return _Class; - - })(); - -}).call(this); - -QuoteBacklink = (function() { - var QuoteBacklink; - - QuoteBacklink = { - containers: $.dict(), - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Backlinks']) { - return; - } - if ((this.bottomBacklinks = Conf['Bottom Backlinks'])) { - $.addClass(doc, 'bottom-backlinks'); - } - Callbacks.Post.push({ - name: 'Quote Backlinking Part 1', - cb: this.firstNode - }); - return Callbacks.Post.push({ - name: 'Quote Backlinking Part 2', - cb: this.secondNode - }); - }, - firstNode: function() { - var a, clone, container, containers, hash, i, j, k, len, len1, len2, link, markYours, nodes, post, quote, ref, ref1; - if (this.isClone || !this.quotes.length || this.isRebuilt) { - return; - } - markYours = Conf['Mark Quotes of You'] && QuoteYou.isYou(this); - a = $.el('a', { - href: g.SITE.Build.postURL(this.board.ID, this.thread.ID, this.ID), - className: this.isHidden ? 'filtered backlink' : 'backlink', - textContent: Conf['backlink'].replace(/%(?:id|%)/g, (function(_this) { - return function(x) { - return { - '%id': _this.ID, - '%%': '%' - }[x]; - }; - })(this)) - }); - if (markYours) { - $.add(a, QuoteYou.mark.cloneNode(true)); - } - ref = this.quotes; - for (i = 0, len = ref.length; i < len; i++) { - quote = ref[i]; - containers = [QuoteBacklink.getContainer(quote)]; - if ((post = g.posts.get(quote)) && post.nodes.backlinkContainer) { - ref1 = post.clones; - for (j = 0, len1 = ref1.length; j < len1; j++) { - clone = ref1[j]; - containers.push(clone.nodes.backlinkContainer); - } - } - for (k = 0, len2 = containers.length; k < len2; k++) { - container = containers[k]; - link = a.cloneNode(true); - nodes = container.firstChild ? [$.tn(' '), link] : [link]; - if (Conf['Quote Previewing']) { - $.on(link, 'mouseover', QuotePreview.mouseover); - } - if (Conf['Quote Inlining']) { - $.on(link, 'click', QuoteInline.toggle); - if (Conf['Quote Hash Navigation']) { - hash = QuoteInline.qiQuote(link, $.hasClass(link, 'filtered')); - nodes.push(hash); - } - } - $.add(container, nodes); - } - } - }, - secondNode: function() { - var container; - if (this.isClone && (this.origin.isReply || Conf['OP Backlinks'])) { - this.nodes.backlinkContainer = $('.container', this.nodes.post); - return; - } - if (!(this.isReply || Conf['OP Backlinks'])) { - return; - } - container = QuoteBacklink.getContainer(this.fullID); - this.nodes.backlinkContainer = container; - if (QuoteBacklink.bottomBacklinks) { - return $.add(this.nodes.post, container); - } else { - return $.add(this.nodes.info, container); - } - }, - getContainer: function(id) { - var base; - return (base = this.containers)[id] || (base[id] = $.el('span', { - className: 'container' - })); - } - }; - - return QuoteBacklink; - -}).call(this); - -QuoteCT = (function() { - var QuoteCT; - - QuoteCT = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Mark Cross-thread Quotes']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - this.mark = $.el('span', { - textContent: '\u00A0(Cross-thread)', - className: 'qmark-ct' - }); - return Callbacks.Post.push({ - name: 'Mark Cross-thread Quotes', - cb: this.node - }); - }, - node: function() { - var board, boardID, i, len, quotelink, ref, ref1, ref2, thread, threadID; - if (this.isClone && this.thread === this.context.thread) { - return; - } - ref = this.context, board = ref.board, thread = ref.thread; - ref1 = this.nodes.quotelinks; - for (i = 0, len = ref1.length; i < len; i++) { - quotelink = ref1[i]; - ref2 = Get.postDataFromLink(quotelink), boardID = ref2.boardID, threadID = ref2.threadID; - if (!threadID) { - continue; - } - if (this.isClone) { - $.rm($('.qmark-ct', quotelink)); - } - if (boardID === board.ID && threadID !== thread.ID) { - $.add(quotelink, QuoteCT.mark.cloneNode(true)); - } - } - } - }; - - return QuoteCT; - -}).call(this); - -QuoteInline = (function() { - var QuoteInline, - slice = [].slice; - - QuoteInline = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Quote Inlining']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Callbacks.Post.push({ - name: 'Quote Inlining', - cb: this.node - }); - }, - node: function() { - var i, isClone, len, link, process, ref; - process = QuoteInline.process; - isClone = this.isClone; - ref = this.nodes.quotelinks.concat(slice.call(this.nodes.backlinks), this.nodes.archivelinks); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - process(link, isClone); - } - }, - process: function(link, clone) { - if (Conf['Quote Hash Navigation']) { - if (!clone) { - $.after(link, QuoteInline.qiQuote(link, $.hasClass(link, 'filtered'))); - } - } - return $.on(link, 'click', QuoteInline.toggle); - }, - qiQuote: function(link, hidden) { - var name; - name = "hashlink"; - if (hidden) { - name += " filtered"; - } - return $.el('a', { - className: name, - textContent: '#', - href: link.href - }); - }, - toggle: function(e) { - var boardID, context, postID, quoter, ref, ref1, threadID; - if ($.modifiedClick(e)) { - return; - } - ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - if (Conf['Inline Cross-thread Quotes Only'] && g.VIEW === 'thread' && ((ref1 = g.posts.get(boardID + "." + postID)) != null ? ref1.nodes.root.offsetParent : void 0)) { - return; - } - if ($.hasClass(doc, 'catalog-mode')) { - return; - } - e.preventDefault(); - quoter = Get.postFromNode(this); - context = quoter.context; - if ($.hasClass(this, 'inlined')) { - QuoteInline.rm(this, boardID, threadID, postID, context); - } else { - if ($.x("ancestor::div[@data-full-i-d='" + boardID + "." + postID + "']", this)) { - return; - } - QuoteInline.add(this, boardID, threadID, postID, context, quoter); - } - return this.classList.toggle('inlined'); - }, - findRoot: function(quotelink, isBacklink) { - if (isBacklink) { - return $.x('ancestor::*[parent::*[contains(@class,"post")]][1]', quotelink); - } else { - return $.x('ancestor-or-self::*[parent::blockquote][1]', quotelink); - } - }, - add: function(quotelink, boardID, threadID, postID, context, quoter) { - var inline, isBacklink, post, qroot, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - inline = $.el('div', { - className: 'inline' - }); - inline.dataset.fullID = boardID + "." + postID; - root = QuoteInline.findRoot(quotelink, isBacklink); - $.after(root, inline); - qroot = $.x('ancestor::*[contains(@class,"postContainer")][1]', root); - $.addClass(qroot, 'hasInline'); - new Fetcher(boardID, threadID, postID, inline, quoter); - if (!((post = g.posts.get(boardID + "." + postID)) && context.thread === post.thread)) { - return; - } - if (isBacklink && Conf['Forward Hiding']) { - $.addClass(post.nodes.root, 'forwarded'); - post.forwarded++ || (post.forwarded = 1); - } - if (!Unread.posts) { - return; - } - return Unread.readSinglePost(post); - }, - rm: function(quotelink, boardID, threadID, postID, context) { - var el, inlined, isBacklink, parentNode, post, qroot, ref, root; - isBacklink = $.hasClass(quotelink, 'backlink'); - root = QuoteInline.findRoot(quotelink, isBacklink); - root = $.x("following-sibling::div[@data-full-i-d='" + boardID + "." + postID + "'][1]", root); - qroot = $.x('ancestor::*[contains(@class,"postContainer")][1]', root); - parentNode = root.parentNode; - $.rm(root); - $.event('PostsRemoved', null, parentNode); - if (!$('.inline', qroot)) { - $.rmClass(qroot, 'hasInline'); - } - if (!(el = root.firstElementChild)) { - return; - } - post = g.posts.get(boardID + "." + postID); - post.rmClone(el.dataset.clone); - if (Conf['Forward Hiding'] && isBacklink && context.thread === g.threads.get(boardID + "." + threadID) && !--post.forwarded) { - delete post.forwarded; - $.rmClass(post.nodes.root, 'forwarded'); - } - while (inlined = $('.inlined', el)) { - ref = Get.postDataFromLink(inlined), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - QuoteInline.rm(inlined, boardID, threadID, postID, context); - $.rmClass(inlined, 'inlined'); - } - } - }; - - return QuoteInline; - -}).call(this); - -QuoteOP = (function() { - var QuoteOP, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - QuoteOP = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Mark OP Quotes']) { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - this.mark = $.el('span', { - textContent: '\u00A0(OP)', - className: 'qmark-op' - }); - return Callbacks.Post.push({ - name: 'Mark OP Quotes', - cb: this.node - }); - }, - node: function() { - var boardID, fullID, i, postID, quotelink, quotelinks, quotes, ref, ref1; - if (this.isClone && this.thread === this.context.thread) { - return; - } - if (!(quotes = this.quotes).length) { - return; - } - quotelinks = this.nodes.quotelinks; - if (this.isClone && (ref = this.thread.fullID, indexOf.call(quotes, ref) >= 0)) { - i = 0; - while (quotelink = quotelinks[i++]) { - $.rm($('.qmark-op', quotelink)); - } - } - fullID = this.context.thread.fullID; - if (indexOf.call(quotes, fullID) < 0) { - return; - } - i = 0; - while (quotelink = quotelinks[i++]) { - ref1 = Get.postDataFromLink(quotelink), boardID = ref1.boardID, postID = ref1.postID; - if ((boardID + "." + postID) === fullID) { - $.add(quotelink, QuoteOP.mark.cloneNode(true)); - } - } - } - }; - - return QuoteOP; - -}).call(this); - -QuotePreview = (function() { - var QuotePreview, - slice = [].slice; - - QuotePreview = { - init: function() { - var ref; - if (!Conf['Quote Previewing']) { - return; - } - if (g.VIEW === 'archive') { - $.on(d, 'mouseover', function(e) { - if (e.target.nodeName === 'A' && $.hasClass(e.target, 'quotelink')) { - return QuotePreview.mouseover.call(e.target, e); - } - }); - } - if ((ref = g.VIEW) !== 'index' && ref !== 'thread') { - return; - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Callbacks.Post.push({ - name: 'Quote Previewing', - cb: this.node - }); - }, - node: function() { - var i, len, link, ref; - ref = this.nodes.quotelinks.concat(slice.call(this.nodes.backlinks), this.nodes.archivelinks); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - $.on(link, 'mouseover', QuotePreview.mouseover); - } - }, - mouseover: function(e) { - var boardID, i, len, origin, post, postID, posts, qp, ref, threadID; - if (($.hasClass(this, 'inlined') && !$.hasClass(doc, 'catalog-mode')) || !d.contains(this)) { - return; - } - ref = Get.postDataFromLink(this), boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - qp = $.el('div', { - id: 'qp', - className: 'dialog' - }); - $.add(Header.hover, qp); - new Fetcher(boardID, threadID, postID, qp, Get.postFromNode(this)); - UI.hover({ - root: this, - el: qp, - latestEvent: e, - endEvents: 'mouseout click', - cb: QuotePreview.mouseout - }); - if (Conf['Quote Highlighting'] && (origin = g.posts.get(boardID + "." + postID))) { - posts = [origin].concat(origin.clones); - posts.pop(); - for (i = 0, len = posts.length; i < len; i++) { - post = posts[i]; - $.addClass(post.nodes.post, 'qphl'); - } - } - }, - mouseout: function() { - var clone, i, len, post, ref, root; - if (!(root = this.el.firstElementChild)) { - return; - } - $.event('PostsRemoved', null, Header.hover); - clone = Get.postFromRoot(root); - post = clone.origin; - post.rmClone(root.dataset.clone); - if (!Conf['Quote Highlighting']) { - return; - } - ref = [post].concat(post.clones); - for (i = 0, len = ref.length; i < len; i++) { - post = ref[i]; - $.rmClass(post.nodes.post, 'qphl'); - } - } - }; - - return QuotePreview; - -}).call(this); - -QuoteStrikeThrough = (function() { - var QuoteStrikeThrough; - - QuoteStrikeThrough = { - init: function() { - var ref; - if (!(((ref = g.VIEW) === 'index' || ref === 'thread') && (Conf['Reply Hiding Buttons'] || (Conf['Menu'] && Conf['Reply Hiding Link']) || Conf['Filter']))) { - return; - } - return Callbacks.Post.push({ - name: 'Strike-through Quotes', - cb: this.node - }); - }, - node: function() { - var boardID, i, len, postID, quotelink, ref, ref1, ref2; - if (this.isClone) { - return; - } - ref = this.nodes.quotelinks; - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - ref1 = Get.postDataFromLink(quotelink), boardID = ref1.boardID, postID = ref1.postID; - if ((ref2 = g.posts.get(boardID + "." + postID)) != null ? ref2.isHidden : void 0) { - $.addClass(quotelink, 'filtered'); - } - } - } - }; - - return QuoteStrikeThrough; - -}).call(this); - -QuoteThreading = -/* - <3 aeosynth - */ - -(function() { - var QuoteThreading; - - QuoteThreading = { - init: function() { - if (!(Conf['Quote Threading'] && g.VIEW === 'thread')) { - return; - } - this.controls = $.el('label', {innerHTML: " Threading"}); - this.threadNewLink = $.el('span', { - className: 'brackets-wrap threadnewlink', - hidden: true - }); - $.extend(this.threadNewLink, {innerHTML: "Thread New Posts"}); - this.input = $('input', this.controls); - this.input.checked = Conf['Thread Quotes']; - $.on(this.input, 'change', this.setEnabled); - $.on(this.input, 'change', this.rethread); - $.on(this.threadNewLink.firstElementChild, 'click', this.rethread); - $.on(d, '4chanXInitFinished', (function(_this) { - return function() { - return _this.ready = true; - }; - })(this)); - Header.menu.addEntry(this.entry = { - el: this.controls, - order: 99 - }); - Callbacks.Thread.push({ - name: 'Quote Threading', - cb: this.setThread - }); - return Callbacks.Post.push({ - name: 'Quote Threading', - cb: this.node - }); - }, - parent: $.dict(), - children: $.dict(), - inserted: $.dict(), - toggleThreading: function() { - return this.setThreadingState(!Conf['Thread Quotes']); - }, - setThreadingState: function(enabled) { - this.input.checked = enabled; - this.setEnabled.call(this.input); - return this.rethread.call(this.input); - }, - setEnabled: function() { - var other, ref; - if (this.checked) { - $.set('Prune All Threads', false); - other = (ref = ReplyPruning.inputs) != null ? ref.enabled : void 0; - if (other != null ? other.checked : void 0) { - other.checked = false; - $.event('change', null, other); - } - } - return $.cb.checked.call(this); - }, - setThread: function() { - QuoteThreading.thread = this; - return $.asap((function() { - return !Conf['Thread Updater'] || $('.navLinksBot > .updatelink'); - }), function() { - var navLinksBot; - if ((navLinksBot = $('.navLinksBot'))) { - return $.add(navLinksBot, [$.tn(' '), QuoteThreading.threadNewLink]); - } - }); - }, - node: function() { - var ancestor, j, lastParent, len, parent, parents, quote, ref; - if (this.isFetchedQuote || this.isClone || !this.isReply) { - return; - } - parents = new Set(); - lastParent = null; - ref = this.quotes; - for (j = 0, len = ref.length; j < len; j++) { - quote = ref[j]; - if (parent = g.posts.get(quote)) { - if (!parent.isFetchedQuote && parent.isReply && parent.ID < this.ID) { - parents.add(parent.ID); - if (!lastParent || parent.ID > lastParent.ID) { - lastParent = parent; - } - } - } - } - if (!lastParent) { - return; - } - ancestor = lastParent; - while (ancestor = QuoteThreading.parent[ancestor.fullID]) { - parents["delete"](ancestor.ID); - } - if (parents.size === 1) { - return QuoteThreading.parent[this.fullID] = lastParent; - } - }, - descendants: function(post) { - var child, children, j, len, posts; - posts = [post]; - if (children = QuoteThreading.children[post.fullID]) { - for (j = 0, len = children.length; j < len; j++) { - child = children[j]; - posts = posts.concat(QuoteThreading.descendants(child)); - } - } - return posts; - }, - insert: function(post) { - var base, child, children, descendants, i, j, k, l, len, name, next, nodes, order, parent, prev, prev2, threadContainer, x; - if (!(Conf['Thread Quotes'] && (parent = QuoteThreading.parent[post.fullID]) && !QuoteThreading.inserted[post.fullID])) { - return false; - } - descendants = QuoteThreading.descendants(post); - if (!Unread.posts.has(parent.ID)) { - if ((function() { - var j, len, x; - for (j = 0, len = descendants.length; j < len; j++) { - x = descendants[j]; - if (Unread.posts.has(x.ID)) { - return true; - } - } - })()) { - QuoteThreading.threadNewLink.hidden = false; - return false; - } - } - order = Unread.order; - children = ((base = QuoteThreading.children)[name = parent.fullID] || (base[name] = [])); - threadContainer = parent.nodes.threadContainer || $.el('div', { - className: 'threadContainer' - }); - nodes = [post.nodes.root]; - if (post.nodes.threadContainer) { - nodes.push(post.nodes.threadContainer); - } - i = children.length; - for (j = children.length - 1; j >= 0; j += -1) { - child = children[j]; - if (child.ID >= post.ID) { - i--; - } - } - if (i !== children.length) { - next = children[i]; - for (k = 0, len = descendants.length; k < len; k++) { - x = descendants[k]; - order.before(order[next.ID], order[x.ID]); - } - children.splice(i, 0, post); - $.before(next.nodes.root, nodes); - } else { - prev = parent; - while ((prev2 = QuoteThreading.children[prev.fullID]) && prev2.length) { - prev = prev2[prev2.length - 1]; - } - for (l = descendants.length - 1; l >= 0; l += -1) { - x = descendants[l]; - order.after(order[prev.ID], order[x.ID]); - } - children.push(post); - $.add(threadContainer, nodes); - } - QuoteThreading.inserted[post.fullID] = true; - if (!parent.nodes.threadContainer) { - parent.nodes.threadContainer = threadContainer; - $.addClass(parent.nodes.root, 'threadOP'); - $.after(parent.nodes.root, threadContainer); - } - return true; - }, - rethread: function() { - var nodes, posts, thread; - if (!QuoteThreading.ready) { - return; - } - thread = QuoteThreading.thread; - posts = thread.posts; - QuoteThreading.threadNewLink.hidden = true; - if (Conf['Thread Quotes']) { - posts.forEach(QuoteThreading.insert); - } else { - nodes = []; - Unread.order = new RandomAccessList(); - QuoteThreading.inserted = $.dict(); - posts.forEach(function(post) { - if (post.isFetchedQuote) { - return; - } - Unread.order.push(post); - if (post.isReply) { - nodes.push(post.nodes.root); - } - if (QuoteThreading.children[post.fullID]) { - delete QuoteThreading.children[post.fullID]; - $.rmClass(post.nodes.root, 'threadOP'); - $.rm(post.nodes.threadContainer); - return delete post.nodes.threadContainer; - } - }); - $.add(thread.nodes.root, nodes); - } - Unread.position = Unread.order.first; - Unread.updatePosition(); - Unread.setLine(true); - Unread.read(); - return Unread.update(); - } - }; - - return QuoteThreading; - -}).call(this); - -QuoteYou = (function() { - var QuoteYou; - - QuoteYou = { - init: function() { - var ref; - if (!Conf['Remember Your Posts']) { - return; - } - this.db = new DataBoard('yourPosts'); - $.sync('Remember Your Posts', function(enabled) { - return Conf['Remember Your Posts'] = enabled; - }); - $.on(d, 'QRPostSuccessful', function(e) { - var cb; - cb = PostRedirect.delay(); - return $.get('Remember Your Posts', Conf['Remember Your Posts'], function(items) { - var boardID, postID, ref, threadID; - if (!items['Remember Your Posts']) { - return; - } - ref = e.detail, boardID = ref.boardID, threadID = ref.threadID, postID = ref.postID; - return QuoteYou.db.set({ - boardID: boardID, - threadID: threadID, - postID: postID, - val: true - }, cb); - }); - }); - if ((ref = g.VIEW) !== 'index' && ref !== 'thread' && ref !== 'archive') { - return; - } - if (Conf['Highlight Own Posts']) { - $.addClass(doc, 'highlight-own'); - } - if (Conf['Highlight Posts Quoting You']) { - $.addClass(doc, 'highlight-you'); - } - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - this.mark = $.el('span', { - textContent: '\u00A0(You)', - className: 'qmark-you' - }); - Callbacks.Post.push({ - name: 'Mark Quotes of You', - cb: this.node - }); - return QuoteYou.menu.init(); - }, - isYou: function(post) { - var ref; - return !!((ref = QuoteYou.db) != null ? ref.get({ - boardID: post.boardID, - threadID: post.threadID, - postID: post.ID - }) : void 0); - }, - node: function() { - var i, len, quotelink, ref; - if (this.isClone) { - return; - } - if (QuoteYou.isYou(this)) { - $.addClass(this.nodes.root, 'yourPost'); - } - if (!this.quotes.length) { - return; - } - ref = this.nodes.quotelinks; - for (i = 0, len = ref.length; i < len; i++) { - quotelink = ref[i]; - if (!(QuoteYou.db.get(Get.postDataFromLink(quotelink)))) { - continue; - } - if (Conf['Mark Quotes of You']) { - $.add(quotelink, QuoteYou.mark.cloneNode(true)); - } - $.addClass(quotelink, 'you'); - $.addClass(this.nodes.root, 'quotesYou'); - } - }, - menu: { - init: function() { - var input, label, ref; - label = $.el('label', { - className: 'toggle-you' - }, {innerHTML: " You"}); - input = $('input', label); - $.on(input, 'change', QuoteYou.menu.toggle); - return (ref = Menu.menu) != null ? ref.addEntry({ - el: label, - order: 80, - open: function(post) { - QuoteYou.menu.post = post.origin || post; - input.checked = QuoteYou.isYou(post); - return true; - } - }) : void 0; - }, - toggle: function() { - var clone, data, i, j, len, len1, post, quotelink, quoter, ref, ref1; - post = QuoteYou.menu.post; - data = { - boardID: post.board.ID, - threadID: post.thread.ID, - postID: post.ID, - val: true - }; - if (this.checked) { - QuoteYou.db.set(data); - } else { - QuoteYou.db["delete"](data); - } - ref = [post].concat(post.clones); - for (i = 0, len = ref.length; i < len; i++) { - clone = ref[i]; - clone.nodes.root.classList.toggle('yourPost', this.checked); - } - ref1 = Get.allQuotelinksLinkingTo(post); - for (j = 0, len1 = ref1.length; j < len1; j++) { - quotelink = ref1[j]; - if (this.checked) { - if (Conf['Mark Quotes of You']) { - $.add(quotelink, QuoteYou.mark.cloneNode(true)); - } - } else { - $.rm($('.qmark-you', quotelink)); - } - quotelink.classList.toggle('you', this.checked); - if ($.hasClass(quotelink, 'quotelink')) { - quoter = Get.postFromNode(quotelink).nodes.root; - quoter.classList.toggle('quotesYou', !!$('.quotelink.you', quoter)); - } - } - } - }, - cb: { - seek: function(type) { - var highlight, highlighted, post, posts, result, str; - highlight = g.SITE.classes.highlight; - if ((highlighted = $("." + highlight))) { - $.rmClass(highlighted, highlight); - } - if (!(QuoteYou.lastRead && doc.contains(QuoteYou.lastRead) && $.hasClass(QuoteYou.lastRead, 'quotesYou'))) { - if (!(post = QuoteYou.lastRead = $('.quotesYou'))) { - new Notice('warning', 'No posts are currently quoting you, loser.', 20); - return; - } - if (QuoteYou.cb.scroll(post)) { - return; - } - } else { - post = QuoteYou.lastRead; - } - str = type + "::div[contains(@class,'quotesYou')]"; - while ((post = (result = $.X(str, post)).snapshotItem(type === 'preceding' ? result.snapshotLength - 1 : 0))) { - if (QuoteYou.cb.scroll(post)) { - return; - } - } - posts = $$('.quotesYou'); - return QuoteYou.cb.scroll(posts[type === 'following' ? 0 : posts.length - 1]); - }, - scroll: function(root) { - var node, post, sel; - post = Get.postFromRoot(root); - if (!post.nodes.post.getBoundingClientRect().height) { - return false; - } else { - QuoteYou.lastRead = root; - location.href = Get.url('post', post); - Header.scrollTo(post.nodes.post); - if (post.isReply) { - sel = "" + g.SITE.selectors.postContainer + g.SITE.selectors.highlightable.reply; - node = post.nodes.root; - if (!node.matches(sel)) { - node = $(sel, node); - } - $.addClass(node, g.SITE.classes.highlight); - } - return true; - } - } - } - }; - - return QuoteYou; - -}).call(this); - -Quotify = (function() { - var Quotify, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, - slice = [].slice; - - Quotify = { - init: function() { - var ref; - if (((ref = g.VIEW) !== 'index' && ref !== 'thread') || !Conf['Resurrect Quotes']) { - return; - } - $.addClass(doc, 'resurrect-quotes'); - if (Conf['Comment Expansion']) { - ExpandComment.callbacks.push(this.node); - } - return Callbacks.Post.push({ - name: 'Resurrect Quotes', - cb: this.node - }); - }, - node: function() { - var deadlink, i, j, len, len1, link, ref, ref1; - if (this.isClone) { - this.nodes.archivelinks = $$('a.linkify.quotelink', this.nodes.comment); - return; - } - ref = $$('a.linkify', this.nodes.comment); - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - Quotify.parseArchivelink.call(this, link); - } - ref1 = $$('.deadlink', this.nodes.comment); - for (j = 0, len1 = ref1.length; j < len1; j++) { - deadlink = ref1[j]; - Quotify.parseDeadlink.call(this, deadlink); - } - }, - parseArchivelink: function(link) { - var boardID, m, postID, ref, threadID; - if (!(m = link.pathname.match(/^\/([^\/]+)\/thread\/S?(\d+)\/?$/))) { - return; - } - if ((ref = link.hostname) === 'boards.4chan.org' || ref === 'boards.4channel.org') { - return; - } - boardID = m[1]; - threadID = m[2]; - postID = link.hash.match(/^#[pq]?(\d+)$|$/)[1] || threadID; - if (Redirect.to('post', { - boardID: boardID, - postID: postID - })) { - $.addClass(link, 'quotelink'); - $.extend(link.dataset, { - boardID: boardID, - threadID: threadID, - postID: postID - }); - return this.nodes.archivelinks.push(link); - } - }, - parseDeadlink: function(deadlink) { - var a, boardID, fetchable, m, post, postID, quote, quoteID, redirect, ref; - if ($.hasClass(deadlink.parentNode, 'prettyprint')) { - Quotify.fixDeadlink(deadlink); - return; - } - quote = deadlink.textContent; - if (!(postID = (ref = quote.match(/\d+$/)) != null ? ref[0] : void 0)) { - return; - } - if (postID[0] === '0') { - Quotify.fixDeadlink(deadlink); - return; - } - boardID = (m = quote.match(/^>>>\/([a-z\d]+)/)) ? m[1] : this.board.ID; - quoteID = boardID + "." + postID; - if (post = g.posts.get(quoteID)) { - if (!post.isDead) { - a = $.el('a', { - href: g.SITE.Build.postURL(boardID, post.thread.ID, postID), - className: 'quotelink', - textContent: quote - }); - } else { - a = $.el('a', { - href: g.SITE.Build.postURL(boardID, post.thread.ID, postID), - className: 'quotelink deadlink', - textContent: quote - }); - $.add(a, Post.deadMark.cloneNode(true)); - $.extend(a.dataset, { - boardID: boardID, - threadID: post.thread.ID, - postID: postID - }); - } - } else { - redirect = Redirect.to('thread', { - boardID: boardID, - threadID: 0, - postID: postID - }); - fetchable = Redirect.to('post', { - boardID: boardID, - postID: postID - }); - if (redirect || fetchable) { - a = $.el('a', { - href: redirect || 'javascript:;', - className: 'deadlink', - textContent: quote - }); - $.add(a, Post.deadMark.cloneNode(true)); - if (fetchable) { - $.addClass(a, 'quotelink'); - $.extend(a.dataset, { - boardID: boardID, - postID: postID - }); - } - } - } - if (indexOf.call(this.quotes, quoteID) < 0) { - this.quotes.push(quoteID); - } - if (!a) { - $.add(deadlink, Post.deadMark.cloneNode(true)); - return; - } - $.replace(deadlink, a); - if ($.hasClass(a, 'quotelink')) { - return this.nodes.quotelinks.push(a); - } - }, - fixDeadlink: function(deadlink) { - var el, green; - if (!(el = deadlink.previousSibling) || el.nodeName === 'BR') { - green = $.el('span', { - className: 'quote' - }); - $.before(deadlink, green); - $.add(green, deadlink); - } - return $.replace(deadlink, slice.call(deadlink.childNodes)); - } - }; - - return Quotify; - -}).call(this); - -Main = (function() { - var Main, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - Main = { - init: function() { - var db, flatten, i, items, j, k, key, len, mountedCB, ref, ref1, ref2, w; - try { - w = window; - if ($.platform === 'crx') { - w = w.wrappedJSObject || w; - } - if ('4chan X antidup' in w) { - return; - } - w['4chan X antidup'] = true; - } catch (error1) {} - try { - if (window.frameElement && ((ref = window.frameElement.src) === '' || ref === 'about:blank')) { - return; - } - } catch (error1) {} - if (doc && $.hasClass(doc, 'fourchan-x')) { - return; - } - $.asap(docSet, function() { - $.addClass(doc, 'fourchan-x', 'seaweedchan'); - if ($.engine) { - return $.addClass(doc, "ua-" + $.engine); - } - }); - $.on(d, '4chanXInitFinished', function() { - if (Main.expectInitFinished) { - return delete Main.expectInitFinished; - } else { - new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); - return $.addClass(doc, 'tainted'); - } - }); - mountedCB = function() { - var cb, j, len, ref1, results; - d.removeEventListener('mounted', mountedCB, true); - Main.isMounted = true; - ref1 = Main.mountedCBs; - results = []; - for (j = 0, len = ref1.length; j < len; j++) { - cb = ref1[j]; - try { - results.push(cb()); - } catch (error1) {} - } - return results; - }; - d.addEventListener('mounted', mountedCB, true); - flatten = function(parent, obj) { - var key, val; - if (obj instanceof Array) { - Conf[parent] = $.dict.clone(obj[0]); - } else if (typeof obj === 'object') { - for (key in obj) { - val = obj[key]; - flatten(key, val); - } - } else { - Conf[parent] = obj; - } - }; - if ((ref1 = location.hostname) === 'boards.4chan.org' || ref1 === 'boards.4channel.org') { - $.global(function() { - var fromCharCode0; - fromCharCode0 = String.fromCharCode; - return String.fromCharCode = function() { - if (document.body) { - String.fromCharCode = fromCharCode0; - } else if (document.currentScript && !document.currentScript.src) { - throw Error(); - } - return fromCharCode0.apply(this, arguments); - }; - }); - $.asap(docSet, function() { - return $.onExists(doc, 'iframe[srcdoc]', $.rm); - }); - } - flatten(null, Config); - ref2 = DataBoard.keys; - for (j = 0, len = ref2.length; j < len; j++) { - db = ref2[j]; - Conf[db] = $.dict(); - } - Conf['customTitles'] = $.dict.clone({ - '4chan.org': { - boards: { - 'qa': { - 'boardTitle': { - orig: '/qa/ - Question & Answer', - title: '/qa/ - 2D/Random' - } - } - } - } - }); - Conf['boardConfig'] = { - boards: $.dict() - }; - Conf['archives'] = Redirect.archives; - Conf['selectedArchives'] = $.dict(); - Conf['cooldowns'] = $.dict(); - Conf['Index Sort'] = $.dict(); - for (i = k = 0; k < 2; i = ++k) { - Conf["Last Long Reply Thresholds " + i] = $.dict(); - } - Conf['siteProperties'] = $.dict(); - Conf['Except Archives from Encryption'] = false; - Conf['JSON Navigation'] = true; - Conf['Oekaki Links'] = true; - Conf['Show Name and Subject'] = false; - Conf['QR Shortcut'] = true; - Conf['Bottom QR Link'] = true; - Conf['Toggleable Thread Watcher'] = true; - Conf['siteSoftware'] = ''; - Conf['Use Faster Image Host'] = 'true'; - Conf['Captcha Fixes'] = true; - Conf['captchaServiceDomain'] = ''; - Conf['captchaServiceKey'] = $.dict(); - if (/\.4chan(?:nel)?\.org$/.test(location.hostname) && !SW.yotsuba.regexp.pass.test(location.href) && !SW.yotsuba.regexp.captcha.test(location.href) && !$$('script:not([src])', d).filter(function(s) { - return /this\[/.test(s.textContent); - }).length) { - ($.getSync || $.get)({ - 'jsWhitelist': Conf['jsWhitelist'] - }, function(arg) { - var jsWhitelist; - jsWhitelist = arg.jsWhitelist; - return $.addCSP("script-src " + (jsWhitelist.replace(/^#.*$/mg, '').replace(/[\s;]+/g, ' ').trim())); - }); - } - items = $.dict(); - for (key in Conf) { - items[key] = void 0; - } - items['previousversion'] = void 0; - return ($.getSync || $.get)(items, function(items) { - var ref3; - if (!$.perProtocolSettings && /\.4chan(?:nel)?\.org$/.test(location.hostname) && ((ref3 = items['Redirect to HTTPS']) != null ? ref3 : Conf['Redirect to HTTPS']) && location.protocol !== 'https:') { - location.replace('https://' + location.host + location.pathname + location.search + location.hash); - return; - } - return $.asap(docSet, function() { - var ref4, val; - if ($.cantSet) { - - } else if (items.previousversion == null) { - Main.isFirstRun = true; - Main.ready(function() { - $.set('previousversion', g.VERSION); - return Settings.open(); - }); - } else if (items.previousversion !== g.VERSION) { - Main.upgrade(items); - } - for (key in Conf) { - val = Conf[key]; - Conf[key] = (ref4 = items[key]) != null ? ref4 : val; - } - return Site.init(Main.initFeatures); - }); - }); - }, - upgrade: function(items) { - var changes, previousversion; - previousversion = items.previousversion; - changes = Settings.upgrade(items, previousversion); - items.previousversion = changes.previousversion = g.VERSION; - return $.set(changes, function() { - var el, ref; - if ((ref = items['Show Updated Notifications']) != null ? ref : true) { - el = $.el('span', {innerHTML: "4chan X has been updated to version " + E(g.VERSION) + "."}); - return new Notice('info', el, 15); - } - }); - }, - parseURL: function(site, url) { - var pathname, r, ref; - if (site == null) { - site = g.SITE; - } - if (url == null) { - url = location; - } - r = {}; - if (!site) { - return r; - } - r.siteID = site.ID; - if (typeof site.isBoardlessPage === "function" ? site.isBoardlessPage(url) : void 0) { - return r; - } - pathname = url.pathname.split(/\/+/); - r.boardID = pathname[1]; - if (site.isFileURL(url)) { - r.VIEW = 'file'; - } else if (typeof site.isAuxiliaryPage === "function" ? site.isAuxiliaryPage(url) : void 0) { - - } else if ((ref = pathname[2]) === 'thread' || ref === 'res') { - r.VIEW = 'thread'; - r.threadID = r.THREADID = +pathname[3].replace(/\.\w+$/, ''); - } else if (pathname[2] === 'archive' && pathname[3] === 'res') { - r.VIEW = 'thread'; - r.threadID = r.THREADID = +pathname[4].replace(/\.\w+$/, ''); - r.threadArchived = true; - } else if (/^(?:catalog|archive)(?:\.\w+)?$/.test(pathname[2])) { - r.VIEW = pathname[2].replace(/\.\w+$/, ''); - } else if (/^(?:index|\d*)(?:\.\w+)?$/.test(pathname[2])) { - r.VIEW = 'index'; - } - return r; - }, - initFeatures: function() { - var base, err, feature, j, len, name, ref, ref1; - $.global(function() { - document.documentElement.classList.add('js-enabled'); - return window.FCX = {}; - }); - Main.jsEnabled = $.hasClass(doc, 'js-enabled'); - if (typeof $.ajaxPageInit === "function") { - $.ajaxPageInit(); - } - $.extend(g, Main.parseURL()); - if (g.boardID) { - g.BOARD = new Board(g.boardID); - } - if (!g.VIEW) { - if (typeof (base = g.SITE).initAuxiliary === "function") { - base.initAuxiliary(); - } - return; - } - if (g.VIEW === 'file') { - $.asap((function() { - return d.readyState !== 'loading'; - }), function() { - var base1, pathname, video; - if (g.SITE.software === 'yotsuba' && Conf['404 Redirect'] && (typeof (base1 = g.SITE).is404 === "function" ? base1.is404() : void 0)) { - pathname = location.pathname.split(/\/+/); - return Redirect.navigate('file', { - boardID: g.BOARD.ID, - filename: pathname[pathname.length - 1] - }); - } else if (video = $('video')) { - if (Conf['Volume in New Tab']) { - Volume.setup(video); - } - if (Conf['Loop in New Tab']) { - video.loop = true; - video.controls = false; - video.play(); - return ImageCommon.addControls(video); - } - } - }); - return; - } - g.threads = new SimpleDict(); - g.posts = new SimpleDict(); - $.onExists(doc, 'body', Main.initStyle); - ref = Main.features; - for (j = 0, len = ref.length; j < len; j++) { - ref1 = ref[j], name = ref1[0], feature = ref1[1]; - if (g.SITE.disabledFeatures && indexOf.call(g.SITE.disabledFeatures, name) >= 0) { - continue; - } - try { - feature.init(); - } catch (error1) { - err = error1; - Main.handleErrors({ - message: "\"" + name + "\" initialization crashed.", - error: err - }); - } - } - return $.ready(Main.initReady); - }, - initStyle: function() { - var keyboard, ref; - if (!Main.isThisPageLegit()) { - return; - } - if ((ref = $('link[href*=mobile]', d.head)) != null) { - ref.disabled = true; - } - doc.dataset.host = location.host; - $.addClass(doc, "sw-" + g.SITE.software); - $.addClass(doc, g.VIEW === 'thread' ? 'thread-view' : g.VIEW); - $.onExists(doc, '.ad-cnt, .adg-rects > .desktop', function(ad) { - return $.onExists(ad, 'img, iframe', function() { - return $.addClass(doc, 'ads-loaded'); - }); - }); - if (Conf['Autohiding Scrollbar']) { - $.addClass(doc, 'autohiding-scrollbar'); - } - $.ready(function() { - if (d.body.clientHeight > doc.clientHeight && (window.innerWidth === doc.clientWidth) !== Conf['Autohiding Scrollbar']) { - Conf['Autohiding Scrollbar'] = !Conf['Autohiding Scrollbar']; - $.set('Autohiding Scrollbar', Conf['Autohiding Scrollbar']); - return $.toggleClass(doc, 'autohiding-scrollbar'); - } - }); - $.addStyle(CSS.sub(CSS.boards), 'fourchanx-css'); - Main.bgColorStyle = $.el('style', { - id: 'fourchanx-bgcolor-css' - }); - keyboard = false; - $.on(d, 'mousedown', function() { - return keyboard = false; - }); - $.on(d, 'keydown', function(e) { - if (e.keyCode === 9) { - return keyboard = true; - } - }); - window.addEventListener('focus', (function() { - return doc.classList.toggle('keyboard-focus', keyboard); - }), true); - return Main.setClass(); - }, - setClass: function() { - var j, knownStyles, len, mainStyleSheet, ref, ref1, setStyle, style, styleSheet, styleSheets; - knownStyles = ['yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'photon', 'tomorrow', 'spooky']; - if (g.SITE.software === 'yotsuba' && g.VIEW === 'catalog') { - if ((mainStyleSheet = $.id('base-css'))) { - style = (ref = mainStyleSheet.href.match(/catalog_(\w+)/)) != null ? ref[1].replace('_new', '').replace(/_+/g, '-') : void 0; - if (indexOf.call(knownStyles, style) >= 0) { - $.addClass(doc, style); - return; - } - } - } - style = mainStyleSheet = styleSheets = null; - setStyle = function() { - var bgColor, css, div, j, len, rgb, s, styleSheet; - if (g.SITE.software === 'yotsuba') { - $.rmClass(doc, style); - style = null; - for (j = 0, len = styleSheets.length; j < len; j++) { - styleSheet = styleSheets[j]; - if (styleSheet.href === (mainStyleSheet != null ? mainStyleSheet.href : void 0)) { - style = styleSheet.title.toLowerCase().replace('new', '').trim().replace(/\s+/g, '-'); - if (style === '_special') { - style = styleSheet.href.match(/[a-z]*(?=[^\/]*$)/)[0]; - } - if (indexOf.call(knownStyles, style) < 0) { - style = null; - } - break; - } - } - if (style) { - $.addClass(doc, style); - $.rm(Main.bgColorStyle); - return; - } - } - div = g.SITE.bgColoredEl(); - div.style.position = 'absolute'; - div.style.visibility = 'hidden'; - $.add(d.body, div); - bgColor = window.getComputedStyle(div).backgroundColor; - $.rm(div); - rgb = bgColor.match(/[\d.]+/g); - if (!/^rgb\(/.test(bgColor)) { - s = window.getComputedStyle(d.body); - bgColor = s.backgroundColor + " " + s.backgroundImage + " " + s.backgroundRepeat + " " + s.backgroundPosition; - } - css = ".dialog, .suboption-list > div:last-of-type, :root.catalog-hover-expand .catalog-container:hover > .post {\n background: " + bgColor + ";\n}\n.unread-mark-read {\n background-color: rgba(" + (rgb.slice(0, 3).join(', ')) + ", " + (0.5 * (rgb[3] || 1)) + ");\n}"; - if ($.luma(rgb) < 100) { - css += ".watch-thread-link {\n background-image: url(\"data:image/svg+xml,\");\n}"; - } - Main.bgColorStyle.textContent = css; - return $.after($.id('fourchanx-css'), Main.bgColorStyle); - }; - $.onExists(d.head, g.SITE.selectors.styleSheet, function(el) { - mainStyleSheet = el; - if (g.SITE.software === 'yotsuba') { - styleSheets = $$('link[rel="alternate stylesheet"]', d.head); - } - new MutationObserver(setStyle).observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - $.on(mainStyleSheet, 'load', setStyle); - return setStyle(); - }); - if (!mainStyleSheet) { - ref1 = $$('link[rel="stylesheet"]', d.head); - for (j = 0, len = ref1.length; j < len; j++) { - styleSheet = ref1[j]; - $.on(styleSheet, 'load', setStyle); - } - return setStyle(); - } - }, - initReady: function() { - var base, base1, msg; - if (typeof (base = g.SITE).is404 === "function" ? base.is404() : void 0) { - if (g.VIEW === 'thread') { - ThreadWatcher.set404(g.BOARD.ID, g.THREADID, function() { - if (Conf['404 Redirect']) { - return Redirect.navigate('thread', { - boardID: g.BOARD.ID, - threadID: g.THREADID, - postID: +location.hash.match(/\d+/) - }, "/" + g.BOARD + "/"); - } - }); - } - return; - } - if (typeof (base1 = g.SITE).isIncomplete === "function" ? base1.isIncomplete() : void 0) { - msg = $.el('div', {innerHTML: "The page didn't load completely.
      Some features may not work unless you reload."}); - $.on($('a', msg), 'click', function() { - return location.reload(); - }); - new Notice('warning', msg); - } - if (g.VIEW === 'catalog') { - return Main.initCatalog(); - } else if (!Index.enabled) { - if (g.SITE.awaitBoard) { - return g.SITE.awaitBoard(Main.initThread); - } else { - return Main.initThread(); - } - } else { - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - } - }, - initThread: function() { - var base, base1, board, errors, posts, ref, s, threads; - s = g.SITE.selectors; - if ((board = $(((ref = s.boardFor) != null ? ref[g.VIEW] : void 0) || s.board))) { - threads = []; - posts = []; - errors = []; - try { - if (typeof (base = g.SITE).preParsingFixes === "function") { - base.preParsingFixes(board); - } - } catch (error1) {} - Main.addThreadsObserver = new MutationObserver(Main.addThreads); - Main.addPostsObserver = new MutationObserver(Main.addPosts); - Main.addThreadsObserver.observe(board, { - childList: true - }); - Main.parseThreads($$(s.thread, board), threads, posts, errors); - if (errors.length) { - Main.handleErrors(errors); - } - if (g.VIEW === 'thread') { - if (g.threadArchived) { - threads[0].isArchived = true; - threads[0].kill(); - } - if (typeof (base1 = g.SITE).parseThreadMetadata === "function") { - base1.parseThreadMetadata(threads[0]); - } - } - Main.callbackNodes('Thread', threads); - return Main.callbackNodesDB('Post', posts, function() { - var j, len, post; - for (j = 0, len = posts.length; j < len; j++) { - post = posts[j]; - QuoteThreading.insert(post); - } - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - }); - } else { - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - } - }, - parseThreads: function(threadRoots, threads, posts, errors) { - var boardID, boardObj, j, len, postRoots, ref, thread, threadID, threadRoot; - for (j = 0, len = threadRoots.length; j < len; j++) { - threadRoot = threadRoots[j]; - boardObj = (boardID = threadRoot.dataset.board) ? (boardID = encodeURIComponent(boardID), g.boards[boardID] || new Board(boardID)) : g.BOARD; - threadID = +threadRoot.id.match(/\d*$/)[0]; - if (!threadID || ((ref = boardObj.threads.get(threadID)) != null ? ref.nodes.root : void 0)) { - return; - } - thread = new Thread(threadID, boardObj); - thread.nodes.root = threadRoot; - threads.push(thread); - postRoots = $$(g.SITE.selectors.postContainer, threadRoot); - if (g.SITE.isOPContainerThread) { - postRoots.unshift(threadRoot); - } - Main.parsePosts(postRoots, thread, posts, errors); - Main.addPostsObserver.observe(threadRoot, { - childList: true - }); - } - }, - parsePosts: function(postRoots, thread, posts, errors) { - var err, j, len, postRoot; - for (j = 0, len = postRoots.length; j < len; j++) { - postRoot = postRoots[j]; - if (!(postRoot.dataset.fullID && g.posts.get(postRoot.dataset.fullID)) && $(g.SITE.selectors.comment, postRoot)) { - try { - posts.push(new Post(postRoot, thread, thread.board)); - } catch (error1) { - err = error1; - errors.push({ - message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.", - error: err, - html: postRoot.outerHTML - }); - } - } - } - }, - addThreads: function(records) { - var errors, j, k, len, len1, node, posts, record, ref, threadRoots, threads; - threadRoots = []; - for (j = 0, len = records.length; j < len; j++) { - record = records[j]; - ref = record.addedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - if (node.nodeType === Node.ELEMENT_NODE && node.matches(g.SITE.selectors.thread)) { - threadRoots.push(node); - } - } - } - if (!threadRoots.length) { - return; - } - threads = []; - posts = []; - errors = []; - Main.parseThreads(threadRoots, threads, posts, errors); - if (errors.length) { - Main.handleErrors(errors); - } - Main.callbackNodes('Thread', threads); - return Main.callbackNodesDB('Post', posts, function() { - return $.event('PostsInserted', null, records[0].target); - }); - }, - addPosts: function(records) { - var anyRemoved, el, errors, j, k, l, len, len1, len2, n, node, postRoots, posts, record, ref, ref1, ref2, thread, threads, threadsRM; - threads = []; - threadsRM = []; - posts = []; - errors = []; - for (j = 0, len = records.length; j < len; j++) { - record = records[j]; - thread = Get.threadFromRoot(record.target); - postRoots = []; - ref = record.addedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - if (node.nodeType === Node.ELEMENT_NODE) { - if (node.matches(g.SITE.selectors.postContainer) || (node = $(g.SITE.selectors.postContainer, node))) { - postRoots.push(node); - } - } - } - n = posts.length; - Main.parsePosts(postRoots, thread, posts, errors); - if (posts.length > n && indexOf.call(threads, thread) < 0) { - threads.push(thread); - } - anyRemoved = false; - ref1 = record.removedNodes; - for (l = 0, len2 = ref1.length; l < len2; l++) { - el = ref1[l]; - if (((ref2 = Get.postFromRoot(el)) != null ? ref2.nodes.root : void 0) === el && !doc.contains(el)) { - anyRemoved = true; - break; - } - } - if (anyRemoved && indexOf.call(threadsRM, thread) < 0) { - threadsRM.push(thread); - } - } - if (errors.length) { - Main.handleErrors(errors); - } - return Main.callbackNodesDB('Post', posts, function() { - var len3, len4, m, o; - for (m = 0, len3 = threads.length; m < len3; m++) { - thread = threads[m]; - $.event('PostsInserted', null, thread.nodes.root); - } - for (o = 0, len4 = threadsRM.length; o < len4; o++) { - thread = threadsRM[o]; - $.event('PostsRemoved', null, thread.nodes.root); - } - }); - }, - initCatalog: function() { - var board, errors, s, threads; - s = g.SITE.selectors.catalog; - if (s && (board = $(s.board))) { - threads = []; - errors = []; - Main.addCatalogThreadsObserver = new MutationObserver(Main.addCatalogThreads); - Main.addCatalogThreadsObserver.observe(board, { - childList: true - }); - Main.parseCatalogThreads($$(s.thread, board), threads, errors); - if (errors.length) { - Main.handleErrors(errors); - } - Main.callbackNodes('CatalogThreadNative', threads); - } - Main.expectInitFinished = true; - return $.event('4chanXInitFinished'); - }, - parseCatalogThreads: function(threadRoots, threads, errors) { - var err, j, len, ref, thread, threadRoot; - for (j = 0, len = threadRoots.length; j < len; j++) { - threadRoot = threadRoots[j]; - try { - thread = new CatalogThreadNative(threadRoot); - if (((ref = thread.thread.catalogViewNative) != null ? ref.nodes.root : void 0) !== threadRoot) { - thread.thread.catalogViewNative = thread; - threads.push(thread); - } - } catch (error1) { - err = error1; - errors.push({ - message: "Parsing of Catalog Thread No." + ((threadRoot.dataset.id || threadRoot.id).match(/\d+/)) + " failed. Thread will be skipped.", - error: err, - html: threadRoot.outerHTML - }); - } - } - }, - addCatalogThreads: function(records) { - var errors, j, k, len, len1, node, record, ref, threadRoots, threads; - threadRoots = []; - for (j = 0, len = records.length; j < len; j++) { - record = records[j]; - ref = record.addedNodes; - for (k = 0, len1 = ref.length; k < len1; k++) { - node = ref[k]; - if (node.nodeType === Node.ELEMENT_NODE && node.matches(g.SITE.selectors.catalog.thread)) { - threadRoots.push(node); - } - } - } - if (!threadRoots.length) { - return; - } - threads = []; - errors = []; - Main.parseCatalogThreads(threadRoots, threads, errors); - if (errors.length) { - Main.handleErrors(errors); - } - return Main.callbackNodes('CatalogThreadNative', threads); - }, - callbackNodes: function(klass, nodes) { - var cb, i, node; - i = 0; - cb = Callbacks[klass]; - while (node = nodes[i++]) { - cb.execute(node); - } - }, - callbackNodesDB: function(klass, nodes, cb) { - var cbs, fn, i, softTask; - i = 0; - cbs = Callbacks[klass]; - fn = function() { - var node; - if (!(node = nodes[i])) { - return false; - } - cbs.execute(node); - return ++i % 25; - }; - softTask = function() { - while (fn()) { - continue; - } - if (!nodes[i]) { - if (cb) { - cb(); - } - return; - } - return setTimeout(softTask, 0); - }; - return softTask(); - }, - handleErrors: function(errors) { - var div, enabled, error, j, len, logs, msg; - if (d.body && $.hasClass(d.body, 'fourchan_x') && !$.hasClass(doc, 'tainted')) { - new Notice('error', 'Error: Multiple copies of 4chan X are enabled.'); - $.addClass(doc, 'tainted'); - } - if (g.SITE.testNativeExtension && !$.hasClass(doc, 'tainted')) { - enabled = g.SITE.testNativeExtension().enabled; - if (enabled) { - $.addClass(doc, 'tainted'); - if (Conf['Disable Native Extension'] && !Main.isFirstRun) { - msg = $.el('div', {innerHTML: "Failed to disable the native extension. You may need to block it."}); - new Notice('error', msg); - } - } - } - if (!(errors instanceof Array)) { - error = errors; - } else if (errors.length === 1) { - error = errors[0]; - } - if (error) { - new Notice('error', Main.parseError(error, Main.reportLink([error])), 15); - return; - } - div = $.el('div', {innerHTML: E(errors.length) + " errors occurred." + (Main.reportLink(errors)).innerHTML + " [show]"}); - $.on(div.lastElementChild, 'click', function() { - var ref; - return ref = this.textContent === 'show' ? ['hide', false] : ['show', true], this.textContent = ref[0], logs.hidden = ref[1], ref; - }); - logs = $.el('div', { - hidden: true - }); - for (j = 0, len = errors.length; j < len; j++) { - error = errors[j]; - $.add(logs, Main.parseError(error)); - } - return new Notice('error', [div, logs], 30); - }, - parseError: function(data, reportLink) { - var context, error, lines, message, ref, ref1; - c.error(data.message, data.error.stack); - message = $.el('div', {innerHTML: E(data.message) + ((reportLink) ? (reportLink).innerHTML : "")}); - error = $.el('div', { - textContent: (data.error.name || 'Error') + ": " + (data.error.message || 'see console for details') - }); - lines = ((ref = data.error.stack) != null ? (ref1 = ref.match(/\d+(?=:\d+\)?$)/mg)) != null ? ref1.join().replace(/^/, ' at ') : void 0 : void 0) || ''; - context = $.el('div', { - textContent: "(4chan X ccd0 v" + g.VERSION + " " + $.platform + " on " + $.engine + lines + ")" - }); - return [message, error, context]; - }, - reportLink: function(errors) { - var addDetails, data, details, info, title, url; - data = errors[0]; - title = data.message; - if (errors.length > 1) { - title += " (+" + (errors.length - 1) + " other errors)"; - } - details = ''; - addDetails = function(text) { - if (!(encodeURIComponent(title + details + text + '\n').length > 8143)) { - return details += text + '\n'; - } - }; - addDetails("[Please describe the steps needed to reproduce this error.]\n\nScript: 4chan X ccd0 v" + g.VERSION + " " + $.platform + "\nURL: " + location.href + "\nUser agent: " + navigator.userAgent); - if ($.platform === 'userscript' && (info = typeof GM !== "undefined" && GM !== null ? GM.info : (typeof GM_info !== "undefined" && GM_info !== null ? GM_info : void 0))) { - addDetails("Userscript manager: " + info.scriptHandler + " " + info.version); - } - addDetails('\n' + data.error); - if (data.error.stack) { - addDetails(data.error.stack.replace(data.error.toString(), '').trim()); - } - if (data.html) { - addDetails('\n`' + data.html + '`'); - } - details = details.replace(/file:\/{3}.+\//g, ''); - url = 'https://github.com/ccd0/4chan-x/issues'.replace('%title', encodeURIComponent(title)).replace('%details', encodeURIComponent(details)); - return {innerHTML: " [report]"}; - }, - isThisPageLegit: function() { - if (!('thisPageIsLegit' in Main)) { - Main.thisPageIsLegit = g.SITE.isThisPageLegit ? g.SITE.isThisPageLegit() : !/^[45]\d\d\b/.test(document.title) && !/\.(?:json|rss)$/.test(location.pathname); - } - return Main.thisPageIsLegit; - }, - ready: function(cb) { - return $.ready(function() { - if (Main.isThisPageLegit()) { - return cb(); - } - }); - }, - mounted: function(cb) { - if (Main.isMounted) { - return cb(); - } else { - return Main.mountedCBs.push(cb); - } - }, - mountedCBs: [], - features: [['Polyfill', Polyfill], ['Board Configuration', BoardConfig], ['Normalize URL', NormalizeURL], ['Delay Redirect on Post', PostRedirect], ['Captcha Configuration', Captcha.replace], ['Image Host Rewriting', ImageHost], ['Redirect', Redirect], ['Header', Header], ['Catalog Links', CatalogLinks], ['Settings', Settings], ['Index Generator', Index], ['Disable Autoplay', AntiAutoplay], ['Announcement Hiding', PSAHiding], ['Fourchan thingies', Fourchan], ['Tinyboard Glue', Tinyboard], ['Color User IDs', IDColor], ['Highlight by User ID', IDHighlight], ['Count Posts by ID', IDPostCount], ['Custom CSS', CustomCSS], ['Thread Links', ThreadLinks], ['Linkify', Linkify], ['Reveal Spoilers', RemoveSpoilers], ['Resurrect Quotes', Quotify], ['Filter', Filter], ['Thread Hiding Buttons', ThreadHiding], ['Reply Hiding Buttons', PostHiding], ['Recursive', Recursive], ['Strike-through Quotes', QuoteStrikeThrough], ['Quick Reply Personas', QR.persona], ['Quick Reply', QR], ['Cooldown', QR.cooldown], ['Post Jumper', PostJumper], ['Pass Link', PassLink], ['Menu', Menu], ['Index Generator (Menu)', Index.menu], ['Report Link', ReportLink], ['Copy Text Link', CopyTextLink], ['Thread Hiding (Menu)', ThreadHiding.menu], ['Reply Hiding (Menu)', PostHiding.menu], ['Delete Link', DeleteLink], ['Filter (Menu)', Filter.menu], ['Edit Link', QR.oekaki.menu], ['Download Link', DownloadLink], ['Archive Link', ArchiveLink], ['Quote Inlining', QuoteInline], ['Quote Previewing', QuotePreview], ['Quote Backlinks', QuoteBacklink], ['Mark Quotes of You', QuoteYou], ['Mark OP Quotes', QuoteOP], ['Mark Cross-thread Quotes', QuoteCT], ['Anonymize', Anonymize], ['Time Formatting', Time], ['Relative Post Dates', RelativeDates], ['File Info Formatting', FileInfo], ['Fappe Tyme', FappeTyme], ['Gallery', Gallery], ['Gallery (menu)', Gallery.menu], ['Sauce', Sauce], ['Image Expansion', ImageExpand], ['Image Expansion (Menu)', ImageExpand.menu], ['Reveal Spoiler Thumbnails', RevealSpoilers], ['Image Loading', ImageLoader], ['Image Hover', ImageHover], ['Volume Control', Volume], ['WEBM Metadata', Metadata], ['Comment Expansion', ExpandComment], ['Thread Expansion', ExpandThread], ['Favicon', Favicon], ['Unread', Unread], ['Unread Line in Index', UnreadIndex], ['Quote Threading', QuoteThreading], ['Thread Stats', ThreadStats], ['Thread Updater', ThreadUpdater], ['Thread Watcher', ThreadWatcher], ['Thread Watcher (Menu)', ThreadWatcher.menu], ['Mark New IPs', MarkNewIPs], ['Index Navigation', Nav], ['Keybinds', Keybinds], ['Banner', Banner], ['Announcements', PSA], ['Flash Features', Flash], ['Reply Pruning', ReplyPruning], ['Mod Contact Links', ModContact]] - }; - - return Main; - -}).call(this); - -Main.init(); - -})(); diff --git a/builds/4chan-X.crx b/builds/4chan-X.crx deleted file mode 100644 index d6deffe5ab..0000000000 Binary files a/builds/4chan-X.crx and /dev/null differ diff --git a/builds/4chan-X.zip b/builds/4chan-X.zip deleted file mode 100644 index b927d4fc9a..0000000000 Binary files a/builds/4chan-X.zip and /dev/null differ diff --git a/crx-chromium-version.txt b/crx-chromium-version.txt deleted file mode 100644 index 2d4f0bd7a1..0000000000 --- a/crx-chromium-version.txt +++ /dev/null @@ -1 +0,0 @@ -Chromium 73.0.3683.75 built on Debian buster/sid, running on Debian buster/sid diff --git a/cspell.json b/cspell.json deleted file mode 100644 index 9f3c446f60..0000000000 --- a/cspell.json +++ /dev/null @@ -1,52 +0,0 @@ -// cSpell Settings -{ - // Version of the setting file. Always 0.2 - "version": "0.2", - // language - current active spelling language - "language": "en", - // words - list of words to be always considered correct - "words": [ - "Backlink", - "backlinks", - "Bitchute", - "burichan", - "capcode", - "Cimeo", - "Clyp", - "Dailymotion", - "fappe", - "ferongr", - "futaba", - "Gfycat", - "greasemonkey", - "iframes", - "Keybinds", - "Linkify", - "Liveleak", - "Pastebin", - "Peertube", - "quotelink", - "quotelinks", - "Soundcloud", - "Streamable", - "Tinyboard", - "tripcode", - "Twitchtv", - "userscript", - "userscripts", - "Vidlii", - "Vocaroo", - "yotsuba" - ], - "ignoreWords": [ - "noupdate", - "tyme", - "werk" - ], - // flagWords - list of words to be always considered incorrect - // This is useful for offensive words and common spelling errors. - // For example "hte" should be "the" - "flagWords": [ - "hte" - ] -} \ No newline at end of file diff --git a/.jshintrc b/misc/.jshintrc similarity index 100% rename from .jshintrc rename to misc/.jshintrc diff --git a/index.html b/misc/index.html similarity index 99% rename from index.html rename to misc/index.html index 32db078d7f..ae78b90ab9 100644 --- a/index.html +++ b/misc/index.html @@ -2,7 +2,7 @@ 4chan X - + diff --git a/template.jst b/misc/template.jst similarity index 98% rename from template.jst rename to misc/template.jst index b561416a28..425d8db34d 100644 --- a/template.jst +++ b/misc/template.jst @@ -2,7 +2,7 @@ 4chan X - + diff --git a/version.json b/misc/version.json similarity index 100% rename from version.json rename to misc/version.json diff --git a/web.css b/misc/web.css similarity index 100% rename from web.css rename to misc/web.css diff --git a/package.json b/package.json index ef704f567f..c5a7b39bca 100644 --- a/package.json +++ b/package.json @@ -139,8 +139,10 @@ }, "type": "module", "scripts": { - "build": "node ./tools/rollup", + "build": "node ./tools/rollup -script -crx", "build:beta": "node ./tools/rollup -beta", - "build:noupdate": "node ./tools/rollup -noupdate" + "build:noupdate": "node ./tools/rollup -noupdate", + "build:crx": "node ./tools/rollup -crx", + "build:script": "node ./tools/rollup -script" } } diff --git a/src/Miscellaneous/NormalizeURL.js b/src/Miscellaneous/NormalizeURL.js index 4df37c6016..0e82a34a32 100644 --- a/src/Miscellaneous/NormalizeURL.js +++ b/src/Miscellaneous/NormalizeURL.js @@ -7,9 +7,10 @@ import { Conf, g } from "../globals/globals"; */ const NormalizeURL = { init() { + let pathname if (!Conf['Normalize URL']) { return; } - let pathname = location.pathname.split(/\/+/); + pathname = location.pathname.split(/\/+/); if (g.SITE.software === 'yotsuba') { switch (g.VIEW) { case 'thread': @@ -21,8 +22,8 @@ const NormalizeURL = { break; } } - - if (location.pathname !== pathname.join('/')) { + pathname = pathname.join('/'); + if (location.pathname !== pathname) { return history.replaceState(history.state, '', `${location.protocol}//${location.host}${pathname}${location.hash}`); } } diff --git a/src/globals/globals.ts b/src/globals/globals.ts index 21a1340e37..0c652bd92a 100644 --- a/src/globals/globals.ts +++ b/src/globals/globals.ts @@ -1,4 +1,4 @@ -import version from "../../version.json"; +import version from "../../misc/version.json"; import meta from "../../package.json"; import type SimpleDict from "../classes/SimpleDict"; import type Post from "../classes/Post"; diff --git a/src/meta/metadata.js b/src/meta/metadata.js index c207b4072f..9b01b50897 100644 --- a/src/meta/metadata.js +++ b/src/meta/metadata.js @@ -10,7 +10,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); export default async function generateMetadata(packageJson, channel) { const meta = packageJson.meta; - const versionFile = await readFile(resolve(__dirname, '../../version.json')); + const versionFile = await readFile(resolve(__dirname, '../../misc/version.json')); const version = JSON.parse(versionFile.toString()); const iconFile = await readFile(resolve(__dirname, './icon48.png')); diff --git a/src/meta/updates.json b/src/meta/updates.json index dc9d876f69..c054a423fb 100644 --- a/src/meta/updates.json +++ b/src/meta/updates.json @@ -3,7 +3,7 @@ "<%= meta.appidGecko %>": { "updates": [ { - "version": "<%= readJSON('/version.json').version %>", + "version": "<%= readJSON('/misc/version.json').version %>", "update_link": "<%= meta.downloads %><%= name %><%= channel %>.crx" } ] diff --git a/src/meta/updates.xml b/src/meta/updates.xml index 9a323082c9..0c8871029a 100644 --- a/src/meta/updates.xml +++ b/src/meta/updates.xml @@ -1,7 +1,7 @@ - ' /> + ' /> diff --git a/src/types/customImports.d.ts b/src/types/customImports.d.ts index 754f1213ce..6d88b57b93 100644 --- a/src/types/customImports.d.ts +++ b/src/types/customImports.d.ts @@ -41,7 +41,7 @@ declare module '*/package.json' { } export default meta; } -declare module '*/version.json' { +declare module '*/misc/version.json' { const versionInfo: { version: string, /** ISO */ diff --git a/tools/bump.js b/tools/bump.js index 2630c2532c..0e94526983 100644 --- a/tools/bump.js +++ b/tools/bump.js @@ -15,11 +15,11 @@ function bump(version, level) { function setversion(version) { var data = {version: version, date: new Date()}; - fs.writeFileSync('version.json', JSON.stringify(data, null, 2)); + fs.writeFileSync('misc/version.json', JSON.stringify(data, null, 2)); } var level = +process.argv[2]; -var v = JSON.parse(fs.readFileSync('version.json', 'utf8')); +var v = JSON.parse(fs.readFileSync('misc/version.json', 'utf8')); var oldversion = v.version; var version = bump(oldversion, level); setversion(version); diff --git a/tools/makeChromium.sh b/tools/makeChromium.sh new file mode 100755 index 0000000000..3233b35a0a --- /dev/null +++ b/tools/makeChromium.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e +cp -r testbuilds/crx builds/4chanXT.chromeium +cp testbuilds/4chan-XT.user.js builds/4chan-XT.user.js diff --git a/tools/rollup.js b/tools/rollup.js index 6d58caf553..53147ce098 100644 --- a/tools/rollup.js +++ b/tools/rollup.js @@ -10,7 +10,7 @@ import generateManifestJson from '../src/meta/manifestJson.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); -const buildDir = resolve(__dirname, '../builds/test/'); +const buildDir = resolve(__dirname, '../testbuilds/'); let channel = ''; @@ -27,7 +27,7 @@ if (process.argv.includes('-beta')) { const license = await readFile(resolve(__dirname, '../LICENSE'), 'utf8'); - const version = JSON.parse(await readFile(resolve(__dirname, '../version.json'), 'utf-8')); + const version = JSON.parse(await readFile(resolve(__dirname, '../misc/version.json'), 'utf-8')); const inlineFile = await setupFileInliner(packageJson); @@ -71,26 +71,25 @@ if (process.argv.includes('-beta')) { }; // user script - await bundle.write({ - ...sharedBundleOpts, - banner: metadata + license, - // file: '../builds/test/rollupOutput.js', - file: resolve(buildDir, `${packageJson.meta.path}${channel}.user.js`), - }); + if (process.argv.includes('-script')) { + await bundle.write({ + ...sharedBundleOpts, + banner: metadata + license, + // file: '../builds/test/rollupOutput.js', + file: resolve(buildDir, `${packageJson.meta.path}${channel}.user.js`), + });} // chrome extension - const crxDir = resolve(buildDir, 'crx'); - await bundle.write({ - ...sharedBundleOpts, - banner: license, - file: resolve(crxDir, 'script.js'), - }); - - await copyFile(resolve(__dirname, '../src/meta/eventPage.js'), resolve(crxDir, 'eventPage.js')); - - writeFile(resolve(crxDir, 'manifest.json'), generateManifestJson(packageJson, version, channel)); - - for (const file of ['icon16.png', 'icon48.png', 'icon128.png']) { - await copyFile(resolve(__dirname, '../src/meta/', file), resolve(crxDir, file)); - }; -})(); + if (process.argv.includes('-crx')) { + const crxDir = resolve(buildDir, 'crx'); + await bundle.write({ + ...sharedBundleOpts, + banner: license, + file: resolve(crxDir, 'script.js'), + }); + await copyFile(resolve(__dirname, '../src/meta/eventPage.js'), resolve(crxDir, 'eventPage.js')); + writeFile(resolve(crxDir, 'manifest.json'), generateManifestJson(packageJson, version, channel)); + for (const file of ['icon16.png', 'icon48.png', 'icon128.png']) { + await copyFile(resolve(__dirname, '../src/meta/', file), resolve(crxDir, file)); + };} + })(); diff --git a/tools/sign.sh b/tools/sign.sh index fc856cc371..cc10c5a54e 100755 --- a/tools/sign.sh +++ b/tools/sign.sh @@ -2,7 +2,7 @@ channel=$1 mkdir -p tmp-crx cp -r "testbuilds/crx$channel" "tmp-crx/crx$channel" -touch -d "$(jq -r '.date' version.json)" "tmp-crx/crx$channel"/* +touch -d "$(jq -r '.date' misc/version.json)" "tmp-crx/crx$channel"/* chromium --pack-extension="tmp-crx/crx$channel" --pack-extension-key="$(dirname "$PWD")/4chan-x.keys/4chan-X.pem" mv "tmp-crx/crx$channel.crx" "testbuilds/4chan-X$channel.crx" rm -r 'tmp-crx/' diff --git a/tools/updcl.js b/tools/updcl.js index 5af377ede3..ab990821fc 100644 --- a/tools/updcl.js +++ b/tools/updcl.js @@ -2,7 +2,7 @@ var fs = require('fs'); var child_process = require('child_process'); var pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); -var v = JSON.parse(fs.readFileSync('version.json', 'utf8')); +var v = JSON.parse(fs.readFileSync('misc/version.json', 'utf8')); var name = pkg.name; var oldVersions = pkg.meta.oldVersions; diff --git a/tools/webstore.js b/tools/webstore.js index 19a72fb8df..ddb25a56d9 100644 --- a/tools/webstore.js +++ b/tools/webstore.js @@ -3,7 +3,7 @@ var child_process = require('child_process'); var request = require('request'); var pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); -var v = JSON.parse(child_process.execSync('git show stable:version.json').toString()); +var v = JSON.parse(child_process.execSync('git show stable:misc/version.json').toString()); var secrets = JSON.parse(fs.readFileSync(`../${pkg.meta.path}.keys/chrome-store.json`, 'utf8')); var refresh = JSON.parse(fs.readFileSync(`../${pkg.meta.path}.keys/refresh-token.json`, 'utf8')); diff --git a/tools/zip-crx.js b/tools/zip-crx.js index 8cd3c605e2..00cfd634e7 100644 --- a/tools/zip-crx.js +++ b/tools/zip-crx.js @@ -2,7 +2,7 @@ var fs = require('fs'); var JSZip = require('jszip'); var pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); -var v = JSON.parse(fs.readFileSync('version.json', 'utf8')); +var v = JSON.parse(fs.readFileSync('misc/version.json', 'utf8')); var channel = process.argv[2] || ''; var zip = new JSZip();