diff --git a/src/Filtering/Filter.ts b/src/Filtering/Filter.ts index a943890..3dd98b5 100644 --- a/src/Filtering/Filter.ts +++ b/src/Filtering/Filter.ts @@ -75,14 +75,13 @@ var Filter = { for (var line of (Conf[key] as string).split('\n')) { let hl: string let isstring: boolean - let regexp: RegExp | string + let regexp: RegExp | string | RegExpMatchArray let top: boolean let types: string[] if (line[0] === '#') { continue } - if (!(regexp = line.match(/\/(.*)\/(\w*)/))) { continue } @@ -109,17 +108,8 @@ var Filter = { regexp = RegExp(regexp[1], regexp[2]) } catch (err) { // I warned you, bro. - new Notice( - 'warning', - [ - $.tn(`Invalid ${key} filter:`), - $.el('br'), - $.tn(line), - $.el('br'), - $.tn(err.message), - ], - 60, - ) + // Notice(type, content, timeout, onclose) + new Notice('error', `Invalid regular expression: ${regexp[1]}`) continue } } @@ -150,14 +140,8 @@ var Filter = { // Highlight the post. // If not specified, the highlight class will be filter-highlight. - if ((hl = /(?:^|;)\s*highlight/.test(filter))) { - hl = - filter.match(/(?:^|;)\s*highlight:([\w-]+)/)?.[1] || - 'filter-highlight' - // Put highlighted OP's thread on top of the board page or not. - // Defaults to on top. - top = filter.match(/(?:^|;)\s*top:(yes|no)/)?.[1] || 'yes' - top = top === 'yes' // Turn it into a boolean + if ((hl = filter.match(/(?:^|;)\s*highlight:([^;]+)/)?.[1])) { + hl = hl.trim() } // Fields that this filter applies to (for 'general' filters) @@ -383,8 +367,8 @@ var Filter = { } } g.BOARD.threads.forEach(function (thread) { - if (thread.catalogViewNative) { - return Filter.catalogNode.call(thread.catalogViewNative) + if (thread.catalogView) { + return Filter.catalogNode.call(thread.catalogView) } }) }, @@ -544,7 +528,7 @@ var Filter = { } const filter = files.map((f) => `/${f.MD5}/`).join('\n') Filter.addFilter('MD5', filter) - const origin = post.origin || post + Filter.showFilters('MD5') if (origin.isReply) { PostHiding.hide(origin) } else if (g.VIEW === 'index') { diff --git a/src/General/Settings.tsx b/src/General/Settings.tsx index 39c485e..2800b63 100644 --- a/src/General/Settings.tsx +++ b/src/General/Settings.tsx @@ -1,11 +1,3 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS205: Consider reworking code to avoid use of IIFEs - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ import SettingsPage from './Settings/SettingsHtml' import FilterGuidePage from './Settings/Filter-guide.html' import SaucePage from './Settings/Sauce.html' @@ -79,12 +71,12 @@ var Settings = { value: { disableAll: true }, }) } - }) + }, Object.create(null)) } else { return $.global(() => Object.defineProperty(window, 'Config', { value: { disableAll: true }, - }), + }), Object.create(null) ) } } @@ -305,7 +297,7 @@ Enable it on boards.${ $('div[data-name="Work around CORB Bug"]', section).hidden = true } - $.get(items, function (items) { + $.get(items, function (items: string[]) { for (key in items) { var val = items[key] inputs[key].checked = val diff --git a/src/Posting/QR.js b/src/Posting/QR.ts similarity index 55% rename from src/Posting/QR.js rename to src/Posting/QR.ts index 5d3f1d6..ce7dba2 100644 --- a/src/Posting/QR.js +++ b/src/Posting/QR.ts @@ -15,29 +15,144 @@ import UI from '../General/UI'; import BoardConfig from '../General/BoardConfig'; import Get from '../General/Get'; import { DAY, dict, SECOND } from '../platform/helpers'; +import Post from '../classes/Post'; +import SimpleDict from '../classes/SimpleDict'; -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS202: Simplify dynamic range loops - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ +interface QRNodes { + initReady(initReady: any): unknown; + postingIsEnabled: boolean; + nodes: any; + open(): unknown; + close(): unknown; + captcha: + | { + init(): any; + moreNeeded(): void; + getThread(): { boardID: string; threadID: string }; + setup(focus: any): any; + destroy(): boolean; + updateThread(): any; + getOne(): {}; + setUsed(): object; + occupied(): boolean; + } + | { + lifetime: number; + init(): void; + timeouts: {}; + prevNeeded: number; + noscriptURL(): string; + moreNeeded(): number; + toggle(): any; + setup(focus: any, force: any): any; + setupNoscript(): any; + setupJS(): object; + afterSetup(mutations: any): void; + setupIFrame(iframe: any): void; + fixQRPosition(): string; + setupTextArea(textarea: any): void; + destroy(): boolean; + getOne(isReply: any): any; + save(pasted: any, token: any): any; + count(): number; + reload(): any; + occupied(): boolean; + }; + min_width: number; + min_height: number; + max_width: number; + max_height: number; + max_size: number; + max_size_video: number; + max_comment: number; + max_width_video: number; + max_height_video: number; + max_duration_video: number; + forcedAnon: boolean; + spoiler: boolean; + link: Element; + getFile(): unknown; + drawFile(): unknown; + setFile(): unknown; + paste(): unknown; + dragOver(): unknown; + dropFile(): unknown; + drag(): unknown; + generatePostableThreadsList(): unknown; + statusCheck(): unknown; + hide(): unknown; + posts: Post[]; + abort(): unknown; + status(): unknown; + quote(): unknown; + unhide(): unknown; + dialog(): unknown; + shortcut(): unknown; + req: any; + cleanNotifications(): unknown; + blur(): unknown; + post: Post; + cooldown: any; + inBubble(): unknown; + hasFocus: any; + texPreviewHide(): unknown; + setCustomCooldown(enabled: boolean): number; + notifications: string[]; + selected: any; + openPost(): void; + openError(): unknown; + error(): unknown; + handleFiles(): unknown; + handleUrl(): unknown; + handleFile(): unknown; + flagsInput(): unknown; + toggleHide(): unknown; + submit(): unknown; + toggleSJIS(): unknown; + texPreviewShow(): unknown; + oekaki: any; + openFileInput(): unknown; + toggleCustomCooldown( + customCooldown: any, + arg1: string, + toggleCustomCooldown: any + ): unknown; + focus(): unknown; + pasteFF: MutationCallback; + persona: any; + flags(): unknown; + response: any; + currentCaptcha: any; + connectionError(): any; + errorCount: any; + waitForThread(): unknown; + characterCount(): unknown; + mimeTypes: string[]; + el: HTMLElement; + validExtension: RegExp; +} -var QR = { - mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], +const QR: QRNodes = { + 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' + 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: { @@ -47,12 +162,14 @@ var QR = { 'application/pdf': 'pdf', 'application/vnd.adobe.flash.movie': 'swf', 'application/x-shockwave-flash': 'swf', - 'video/webm': 'webm' + 'video/webm': 'webm', }, init() { - let sc; - if (!Conf['Quick Reply']) { return; } + let sc: HTMLElement; + if (!Conf['Quick Reply']) { + return; + } this.posts = []; @@ -60,18 +177,19 @@ var QR = { Callbacks.Post.push({ name: 'Quick Reply', - cb: this.node + cb: this.node, }); - this.shortcut = (sc = $.el('a', { + 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; } + 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(); @@ -84,38 +202,40 @@ var QR = { }, initReady() { - let origToggle; - const captchaVersion = $('#g-recaptcha, #captcha-forced-noscript') ? 'v2' : 't'; + let origToggle: any; + const captchaVersion = $('#g-recaptcha, #captcha-forced-noscript') + ? 'v2' + : 't'; QR.captcha = Captcha[captchaVersion]; QR.postingIsEnabled = true; - const {config} = g.BOARD; + const { config } = g.BOARD; const prop = (key, def) => +(config[key] ?? def); - QR.min_width = prop('min_image_width', 1); + 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_width = QR.max_height = 10000; - QR.max_size = prop('max_filesize', 4194304); + 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_comment = prop('max_comment_chars', 2000); - QR.max_width_video = (QR.max_height_video = 2048); + 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; + QR.spoiler = !!config.spoilers; - if (origToggle = $.id('togglePostFormLink')) { - const link = $.el('h1', - {className: "qr-link-container"}); + if ((origToggle = $.id('togglePostFormLink'))) { + const link = $.el('h1', { className: 'qr-link-container' }); $.extend(link, { - innerHTML: - `${g.VIEW === "thread" ? "Reply to Thread" : "Start a Thread"}` + innerHTML: `${ + g.VIEW === 'thread' ? 'Reply to Thread' : 'Start a Thread' + }`, }); QR.link = link.firstElementChild; - $.on(link.firstChild, 'click', function() { + $.on(link.firstChild, 'click', function () { QR.open(); return QR.nodes.com.focus(); }); @@ -125,40 +245,52 @@ var QR = { } if (g.VIEW === 'thread') { - let navLinksBot; - const linkBot = $.el('div', - {className: "brackets-wrap qr-link-container-bottom"}); - $.extend(linkBot, {innerHTML: 'Reply to Thread'}); + let navLinksBot: HTMLElement; + const linkBot = $.el('div', { + className: 'brackets-wrap qr-link-container-bottom', + }); + $.extend(linkBot, { + innerHTML: + 'Reply to Thread', + }); - $.on(linkBot.firstElementChild, 'click', function() { + $.on(linkBot.firstElementChild, 'click', function () { QR.open(); return QR.nodes.com.focus(); }); - if (navLinksBot = $('.navLinksBot')) { $.prepend(navLinksBot, linkBot); } + if ((navLinksBot = $('.navLinksBot'))) { + $.prepend(navLinksBot, linkBot); + } } - $.on(d, 'QRGetFile', QR.getFile); - $.on(d, 'QRDrawFile', QR.drawFile); - $.on(d, 'QRSetFile', QR.setFile); + $.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, '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; } + if (!Conf['Persistent QR']) { + return; + } QR.open(); - if (Conf['Auto Hide QR']) { return QR.hide(); } + if (Conf['Auto Hide QR']) { + return QR.hide(); + } }, statusCheck() { - if (!QR.nodes) { return; } - const {thread} = QR.posts[0]; - if ((thread !== 'new') && g.threads.get(`${g.BOARD}.${thread}`).isDead) { + if (!QR.nodes) { + return; + } + const { thread } = QR.posts[0]; + if (thread !== 'new' && g.threads.get(`${g.BOARD}.${thread}`).isDead) { return QR.abort(); } else { return QR.status(); @@ -167,12 +299,16 @@ var QR = { node() { $.on(this.nodes.quote, 'click', QR.quote); - if (this.isFetchedQuote) { return QR.generatePostableThreadsList(); } + if (this.isFetchedQuote) { + return QR.generatePostableThreadsList(); + } }, open() { if (QR.nodes) { - if (QR.nodes.el.hidden) { QR.captcha.setup(); } + if (QR.nodes.el.hidden) { + QR.captcha.setup(); + } QR.nodes.el.hidden = false; QR.unhide(); } else { @@ -182,7 +318,7 @@ var QR = { delete QR.nodes; Main.handleErrors({ message: 'Quick Reply dialog creation crashed.', - error: err + error: err, }); return; } @@ -210,7 +346,7 @@ var QR = { }, focus() { - return $.queueTask(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); @@ -219,19 +355,28 @@ var QR = { }, inBubble() { - const bubbles = $$('iframe[src^="https://www.google.com/recaptcha/api2/frame"]'); - return bubbles.includes(d.activeElement) || bubbles.some(el => (getComputedStyle(el).visibility !== 'hidden') && (el.getBoundingClientRect().bottom > 0)); + const bubbles = $$( + 'iframe[src^="https://www.google.com/recaptcha/api2/frame"]' + ); + return ( + bubbles.includes(d.activeElement) || + bubbles.some( + el => + getComputedStyle(el).visibility !== 'hidden' && + el.getBoundingClientRect().bottom > 0 + ) + ); }, hide() { QR.blur(); $.addClass(QR.nodes.el, 'autohide'); - return QR.nodes.autohide.checked = true; + return (QR.nodes.autohide.checked = true); }, unhide() { $.rmClass(QR.nodes.el, 'autohide'); - return QR.nodes.autohide.checked = false; + return (QR.nodes.autohide.checked = false); }, toggleHide() { @@ -243,7 +388,9 @@ var QR = { }, blur() { - if (QR.nodes.el.contains(d.activeElement)) { return d.activeElement.blur(); } + if (QR.nodes.el.contains(d.activeElement)) { + return d.activeElement.blur(); + } }, toggleSJIS(e) { @@ -254,7 +401,9 @@ var QR = { }, texPreviewShow() { - if ($.hasClass(QR.nodes.el, 'tex-preview')) { return QR.texPreviewHide(); } + 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); @@ -265,7 +414,7 @@ var QR = { }, addPost() { - const wasOpen = (QR.nodes && !QR.nodes.el.hidden); + const wasOpen = QR.nodes && !QR.nodes.el.hidden; QR.open(); if (wasOpen) { $.addClass(QR.nodes.el, 'dump'); @@ -298,34 +447,36 @@ var QR = { const notice = new Notice('warning', el); QR.notifications.push(notice); if (!Header.areNotificationsEnabled) { - if (d.hidden && !QR.cooldown.auto) { return alert(el.textContent); } + if (d.hidden && !QR.cooldown.auto) { + return alert(el.textContent); + } } else if (d.hidden || !(focusOverride || d.hasFocus())) { const notif = new Notification(el.textContent, { body: el.textContent, - icon: Favicon.logo - } - ); + icon: Favicon.logo, + }); notif.onclick = () => window.focus(); if ($.engine !== 'gecko') { // Firefox automatically closes notifications // so we can't control the onclose properly. notif.onclose = () => notice.close(); - return notif.onshow = () => setTimeout(function() { - notif.onclose = null; - return notif.close(); - } - , 7 * SECOND); + return (notif.onshow = () => + setTimeout(function () { + notif.onclose = null; + return notif.close(); + }, 7 * SECOND)); } } }, connectionError() { - return $.el('span', - { innerHTML: + return $.el('span', { + innerHTML: 'Connection error while posting. ' + - '[More info]' - } - ); + '[More info]', + }); }, notifications: [], @@ -334,55 +485,62 @@ var QR = { for (var notification of QR.notifications) { notification.close(); } - return QR.notifications = []; + return (QR.notifications = []); }, status() { let disabled, value; - if (!QR.nodes) { return; } - const {thread} = QR.posts[0]; - if ((thread !== 'new') && g.threads.get(`${g.BOARD}.${thread}`).isDead) { - value = 'Dead'; + if (!QR.nodes) { + return; + } + const { thread } = QR.posts[0]; + 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; + value = QR.req ? QR.req.progress : QR.cooldown.seconds || value; - const {status} = QR.nodes; - status.value = !value ? - 'Submit' - : QR.cooldown.auto ? - `Auto ${value}` - : - value; - return status.disabled = disabled || false; + const { status } = QR.nodes; + status.value = !value + ? 'Submit' + : QR.cooldown.auto + ? `Auto ${value}` + : value; + return (status.disabled = disabled || false); }, openPost() { QR.open(); if (QR.selected.isLocked) { const index = QR.posts.indexOf(QR.selected); - (QR.posts[index+1] || new QR.post()).select(); + (QR.posts[index + 1] || new QR.post()).select(); $.addClass(QR.nodes.el, 'dump'); - return QR.cooldown.auto = true; + return (QR.cooldown.auto = true); } }, quote(e) { let range; e?.preventDefault(); - if (!QR.postingIsEnabled) { return; } - const sel = d.getSelection(); + if (!QR.postingIsEnabled) { + return; + } + const sel = d.getSelection(); const post = Get.postFromNode(this); - const {root} = post.nodes; + const { root } = post.nodes; const postRange = new Range(); postRange.selectNode(root); - let text = post.board.ID === g.BOARD.ID ? `>>${post}\n` : `>>>/${post.board}/${post}\n`; - for (let i = 0, end = sel.rangeCount, asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) { + let text = + post.board.ID === g.BOARD.ID + ? `>>${post}\n` + : `>>>/${post.board}/${post}\n`; + for ( + let i = 0, end = sel.rangeCount, asc = 0 <= end; + asc ? i < end : i > end; + asc ? i++ : i-- + ) { try { var insideCode, node; range = sel.getRangeAt(i); @@ -394,53 +552,74 @@ var QR = { range.setEndAfter(root); } - if (!range.toString().trim()) { continue; } + if (!range.toString().trim()) { + continue; + } - var frag = range.cloneContents(); + var frag = range.cloneContents(); var ancestor = range.commonAncestorContainer; // Quoting the insides of a spoiler/code tag. - if ($.x('ancestor-or-self::*[self::s or contains(@class,"removed-spoiler")]', ancestor)) { + 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)) { + if ( + (insideCode = $.x( + 'ancestor-or-self::pre[contains(@class,"prettyprint")]', + ancestor + )) + ) { $.prepend(frag, $.tn('[code]')); $.add(frag, $.tn('[/code]')); } - for (node of $$((insideCode ? 'br' : '.prettyprint br'), frag)) { + for (node of $$(insideCode ? 'br' : '.prettyprint br', frag)) { $.replace(node, $.tn('\n')); } for (node of $$('br', frag)) { - if (node !== frag.lastChild) { $.replace(node, $.tn('\n>')); } + if (node !== frag.lastChild) { + $.replace(node, $.tn('\n>')); + } } g.SITE.insertTags?.(frag); for (node of $$('.linkify[data-original]', frag)) { $.replace(node, $.tn(node.dataset.original)); } for (node of $$('.embedder', frag)) { - if (node.previousSibling?.nodeValue === ' ') { $.rm(node.previousSibling); } + if (node.previousSibling?.nodeValue === ' ') { + $.rm(node.previousSibling); + } $.rm(node); } text += `>${frag.textContent.trim()}\n`; - } catch (error) { } + } catch (error) {} } QR.openPost(); - const {com, thread} = QR.nodes; - if (!com.value) { thread.value = Get.threadFromNode(this); } + const { com, thread } = QR.nodes; + if (!com.value) { + thread.value = Get.threadFromNode(this); + } const wasOnlyQuotes = QR.selected.isOnlyQuotes(); const caretPos = com.selectionStart; // Replace selection for text. - com.value = com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); + com.value = + com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); // Move the caret to the end of the new quote. range = caretPos + text.length; com.setSelectionRange(range, range); com.focus(); // This allows us to determine if any text other than quotes has been typed. - if (wasOnlyQuotes) { QR.selected.quotedText = com.value; } + if (wasOnlyQuotes) { + QR.selected.quotedText = com.value; + } QR.selected.save(com); return QR.selected.save(thread); @@ -448,10 +627,16 @@ var QR = { characterCount() { const counter = QR.nodes.charCount; - const count = QR.nodes.com.value.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length; + const 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'); + counter.hidden = count < QR.max_comment / 2; + return (count > QR.max_comment ? $.addClass : $.rmClass)( + counter, + 'warning' + ); }, getFile() { @@ -460,31 +645,39 @@ var QR = { drawFile(e) { const file = QR.selected?.file; - if (!file || !/^(image|video)\//.test(file.type)) { return; } + if (!file || !/^(image|video)\//.test(file.type)) { + return; + } const isVideo = /^video\//.test(file); - const el = $.el((isVideo ? 'video' : 'img')); + const el = $.el(isVideo ? 'video' : 'img'); $.on(el, 'error', () => QR.openError()); - $.on(el, (isVideo ? 'loadeddata' : 'load'), function() { + $.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); + return (el.src = URL.createObjectURL(file)); }, openError() { const div = $.el('div'); $.extend(div, { innerHTML: - 'Could not open file. [More info]' + 'Could not open file. [More info]', }); return QR.error(div); }, setFile(e) { - const {file, name, source} = e.detail; - if (name != null) { file.name = name; } - if (source != null) { file.source = source; } + const { file, name, source } = e.detail; + if (name != null) { + file.name = name; + } + if (source != null) { + file.source = source; + } QR.open(); return QR.handleFiles([file]); }, @@ -493,30 +686,35 @@ var QR = { // Let it drag anything from the page. const toggle = e.type === 'dragstart' ? $.off : $.on; toggle(d, 'dragover', QR.dragOver); - return toggle(d, 'drop', QR.dropFile); + return toggle(d, 'drop', QR.dropFile); }, dragOver(e) { e.preventDefault(); - return e.dataTransfer.dropEffect = 'copy'; + return (e.dataTransfer.dropEffect = 'copy'); }, // cursor feedback dropFile(e) { // Let it only handle files from the desktop. - if (!e.dataTransfer.files.length) { return; } + if (!e.dataTransfer.files.length) { + return; + } e.preventDefault(); QR.open(); return QR.handleFiles(e.dataTransfer.files); }, paste(e) { - if (!e.clipboardData.items) { return; } + if (!e.clipboardData.items) { + return; + } let file = null; let score = -1; for (var item of e.clipboardData.items) { var file2; - if ((item.kind === 'file') && (file2 = item.getAsFile())) { - var score2 = (2*(file2.size <= QR.max_size)) + (file2.type === 'image/png'); + if (item.kind === 'file' && (file2 = item.getAsFile())) { + var score2 = + 2 * (file2.size <= QR.max_size) + (file2.type === 'image/png'); if (score2 > score) { file = file2; score = score2; @@ -524,9 +722,11 @@ var QR = { } } if (file) { - const {type} = file; - const blob = new Blob([file], {type}); - blob.name = `${Conf['pastedname']}.${$.getOwn(QR.extensionFromType, type) || 'jpg'}`; + const { type } = file; + const blob = new Blob([file], { type }); + blob.name = `${Conf['pastedname']}.${ + $.getOwn(QR.extensionFromType, type) || 'jpg' + }`; QR.open(); QR.handleFiles([blob]); $.addClass(QR.nodes.el, 'dump'); @@ -534,20 +734,26 @@ var QR = { }, pasteFF() { - const {pasteArea} = QR.nodes; - if (!pasteArea.childNodes.length) { return; } + const { pasteArea } = QR.nodes; + if (!pasteArea.childNodes.length) { + return; + } const images = $$('img', pasteArea); $.rmAll(pasteArea); for (var img of images) { var m; - var {src} = img; - if (m = src.match(/data:(image\/(\w+));base64,(.+)/)) { + var { src } = img; + if ((m = src.match(/data:(image\/(\w+));base64,(.+)/))) { var bstr = atob(m[3]); var arr = new Uint8Array(bstr.length); - for (var i = 0, end = bstr.length, asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) { + for ( + var i = 0, end = bstr.length, asc = 0 <= end; + asc ? i < end : i > end; + asc ? i++ : i-- + ) { arr[i] = bstr.charCodeAt(i); } - var blob = new Blob([arr], {type: m[1]}); + var blob = new Blob([arr], { type: m[1] }); blob.name = `${Conf['pastedname']}.${m[2]}`; QR.handleFiles([blob]); } else if (/^https?:\/\//.test(src)) { @@ -559,32 +765,46 @@ var QR = { handleUrl(urlDefault) { QR.open(); QR.selected.preventAutoPost(); - return CrossOrigin.permission(function() { - const 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."); + return CrossOrigin.permission( + function () { + const 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."); + } + }); + }, + function () { + return QR.error("Can't load file."); + } + ); }, - handleFiles(files) { - if (this !== QR) { // file input - files = [...Array.from(this.files)]; + if (this !== QR) { + // file input + files = [...Array.from(this.files)]; this.value = null; } - if (!files.length) { return; } + if (!files.length) { + return; + } QR.cleanNotifications(); for (var file of files) { 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')) { + 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(); } }, @@ -604,146 +824,170 @@ var QR = { }, openFileInput() { - if (QR.nodes.fileButton.disabled) { return; } + if (QR.nodes.fileButton.disabled) { + return; + } QR.nodes.fileInput.click(); return QR.nodes.fileButton.focus(); }, generatePostableThreadsList() { - if (!QR.nodes) { return; } - const list = QR.nodes.thread; + if (!QR.nodes) { + return; + } + const list = QR.nodes.thread; const options = [list.firstElementChild]; for (var thread of g.BOARD.threads.keys) { - options.push($.el('option', { - value: thread, - textContent: `Thread ${thread}` - } - ) + options.push( + $.el('option', { + value: thread, + textContent: `Thread ${thread}`, + }) ); } const val = list.value; $.rmAll(list); $.add(list, options); list.value = val; - if (list.value === val) { return; } + if (list.value === val) { + return; + } // Fix the value if the option disappeared. - list.value = g.VIEW === 'thread' ? - g.THREADID - : - 'new'; - return (g.VIEW === 'thread' ? $.addClass : $.rmClass)(QR.nodes.el, 'reply-to-thread'); + list.value = g.VIEW === 'thread' ? g.THREADID : 'new'; + return (g.VIEW === 'thread' ? $.addClass : $.rmClass)( + QR.nodes.el, + 'reply-to-thread' + ); }, dialog() { let dialog, event, nodes; let name; - QR.nodes = (nodes = { - el: (dialog = UI.dialog('qr', - { innerHTML: QuickReplyPage })) - }); + QR.nodes = nodes = { + el: (dialog = UI.dialog('qr', { innerHTML: QuickReplyPage })), + }; - const setNode = (name, query) => nodes[name] = $(query, dialog); + const setNode = (name, query) => (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('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]'); + setNode('dumpButton', '#dump-button'); + setNode('status', '[type=submit]'); + setNode('flashTag', '[name=filetag]'); + setNode('fileInput', '[type=file]'); - const {config} = g.BOARD; - const {classList} = QR.nodes.el; - 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); + const { config } = g.BOARD; + const { classList } = QR.nodes.el; + 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']); + 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({customCooldownEnabled}) { - QR.setCustomCooldown(customCooldownEnabled); - return $.sync('customCooldownEnabled', QR.setCustomCooldown); - }); + $.get( + 'customCooldownEnabled', + Conf['customCooldownEnabled'], + function ({ 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', () => 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', () => QR.selected.nodes.spoiler.click()); - $.on(nodes.oekakiButton, 'click', QR.oekaki.button); - $.on(nodes.fileRM, 'click', () => QR.selected.rmFile()); - $.on(nodes.urlButton, 'click', () => QR.handleUrl('')); - $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); - $.on(nodes.dumpButton, 'click', () => nodes.el.classList.toggle('dump')); - $.on(nodes.fileInput, 'change', QR.handleFiles); + $.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', () => 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', () => QR.selected.nodes.spoiler.click()); + $.on(nodes.oekakiButton, 'click', QR.oekaki.button); + $.on(nodes.fileRM, 'click', () => QR.selected.rmFile()); + $.on(nodes.urlButton, 'click', () => QR.handleUrl('')); + $.on(nodes.customCooldown, 'click', QR.toggleCustomCooldown); + $.on(nodes.dumpButton, 'click', () => nodes.el.classList.toggle('dump')); + $.on(nodes.fileInput, 'change', QR.handleFiles); window.addEventListener('focus', QR.focus, true); - window.addEventListener('blur', QR.focus, true); + window.addEventListener('blur', QR.focus, true); // We don't receive blur events from captcha iframe. $.on(d, 'click', QR.focus); // XXX Workaround for image pasting in Firefox, obsolete as of v50. // https://bugzilla.mozilla.org/show_bug.cgi?id=906420 - if (($.engine === 'gecko') && !window.DataTransferItemList) { + if ($.engine === 'gecko' && !window.DataTransferItemList) { nodes.pasteArea.hidden = false; } - new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, {childList: true}); + new MutationObserver(QR.pasteFF).observe(nodes.pasteArea, { + childList: true, + }); // save selected post's data const items = ['thread', 'name', 'email', 'sub', 'com', 'filename', 'flag']; let i = 0; - const save = function() { return QR.selected.save(this); }; + const save = function () { + return QR.selected.save(this); + }; while ((name = items[i++])) { var node; - if (!(node = nodes[name])) { continue; } + if (!(node = nodes[name])) { + continue; + } event = node.nodeName === 'SELECT' ? 'change' : 'input'; $.on(nodes[name], event, save); } // XXX Blink and WebKit treat width and height of