diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8294e3a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "search.exclude": { + "*.jst": true, + "*.md": true, + "*.yaml": true, + "package*.json": true + } +} \ No newline at end of file diff --git a/src/Linkification/Embedding.js b/src/Linkification/Embedding.js index 5bb5eae..3495d1d 100644 --- a/src/Linkification/Embedding.js +++ b/src/Linkification/Embedding.js @@ -318,54 +318,52 @@ var Embedding = { return $.toggleClass(this, 'embed-removed') } }, - + title(req, data) { - let text - const { key, uid, options, link, post } = data - const service = Embedding.types[key].title - - let { status } = req + const { key, uid, options, link, post } = data; + const service = Embedding.types[key].title; + + let status = req.status; if ([200, 304].includes(status) && service.status) { - status = service.status(req.response)[0] + status = service.status(req.response)[0]; } - + if (!status) { - return + return; } - - text = `[${key}] ${(() => { + + const getText = () => { switch (status) { case 200: case 304: - text = service.text(req.response, uid) - if (typeof text === 'string') { - return text - } else { - return (text = link.textContent) - } + const text = service.text(req.response, uid); + return typeof text === 'string' ? text : link.textContent; case 404: - return 'Not Found' + return 'Not Found'; case 403: case 401: - return 'Forbidden or Private' + return 'Forbidden or Private'; default: - return `${status}'d` + return `${status}'d`; } - })()}` - - link.dataset.original = link.textContent - link.textContent = text - for (var post2 of post.clones) { - for (var link2 of $$('a.linkify', post2.nodes.comment)) { + }; + + const text = `[${key}] ${getText()}`; + + link.dataset.original = link.textContent; + link.textContent = text; + + for (const post2 of post.clones) { + for (const link2 of $$('a.linkify', post2.nodes.comment)) { if (link2.href === link.href) { if (link2.dataset.original == null) { - link2.dataset.original = link2.textContent + link2.dataset.original = link2.textContent; } - link2.textContent = text + link2.textContent = text; } } } - }, + } }, ordered_types: [ diff --git a/src/Miscellaneous/ExpandComment.js b/src/Miscellaneous/ExpandComment.js index 5406715..8d6be4e 100644 --- a/src/Miscellaneous/ExpandComment.js +++ b/src/Miscellaneous/ExpandComment.js @@ -73,7 +73,7 @@ var ExpandComment = { parse(req, a, post) { let postObj, spoilerRange - const { status } = req + const { status } = req.status if (![200, 304].includes(status)) { a.textContent = status ? `Error ${req.statusText} (${status})` diff --git a/src/classes/Fetcher.js b/src/classes/Fetcher.js index 50a6932..48c5bee 100644 --- a/src/classes/Fetcher.js +++ b/src/classes/Fetcher.js @@ -11,15 +11,7 @@ import CrossOrigin from '../platform/CrossOrigin' import Get from '../General/Get' import { dict } from '../platform/helpers' -/* - * 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 - * DS206: Consider reworking classes to avoid initClass - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ + export default class Fetcher { static initClass() { this.prototype.archiveTags = { @@ -88,20 +80,53 @@ export default class Fetcher { this.root.textContent = `Loading post No.${this.postID}...` if (this.threadID) { const that = this - $.cache( - g.SITE.urls.threadJSON({ - boardID: this.boardID, - threadID: this.threadID, - }), - function ({ isCached }) { - return that.fetchedPost(this, isCached) + Fetcher.fetchThread( + this.boardID, + this.threadID, + function (req, isCached) { + that.fetchedThread(req, isCached) }, + true, ) } else { - this.archivedPost() + const that = this + Fetcher.fetchPost( + this.boardID, + this.postID, + function (req, isCached) { + that.fetchedPost(req, isCached) + }, + true, + ) + } + } + + fetchedThread(req) { + const { status, response } = req + const { boardID, threadID } = this + const board = g.boards[boardID] + if (status === 404) { + this.root.textContent = `Thread No.${threadID} not found.` + return + } + if (status !== 200) { + this.root.textContent = `Error loading thread No.${threadID}.` + return + } + if (response === '') { + this.root.textContent = `Thread No.${threadID} is empty.` + return + } + const thread = new Thread( + g.SITE.Build.threadFromObject(response, boardID),board) + Main.callbackNodes('Thread', [thread]) + const post = thread.posts.get(this.postID) + if (post) { + this.insert(post) + } else { + this.root.textContent = `Post No.${this.postID} not found.` } } - insert(post) { // Stop here if the container has been removed while loading. if (!this.root.parentNode) { @@ -155,76 +180,75 @@ export default class Fetcher { } fetchedPost(req, isCached) { - // In case of multiple callbacks for the same request, - // don't parse the same original post more than once. - let post - if ((post = g.posts.get(`${this.boardID}.${this.postID}`))) { - this.insert(post) - return + const { status, response } = req; + const { boardID, postID, threadID } = this; + const postKey = `${boardID}.${postID}`; + + const post = g.posts.get(postKey); + if (post) { + this.insert(post); + return; } - - const { status } = req + if (status !== 200) { - // The thread can die by the time we check a quote. - 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 + this.handleNon200Status(status); + return; } - - const { posts } = req.response - g.SITE.Build.spoilerRange[this.boardID] = posts[0].custom_spoiler - for (post of posts) { - if (post.no === this.postID) { - break - } - } // we found it! - - if (post.no !== this.postID) { - // Cached requests can be stale and must be rechecked. - if (isCached) { - const api = g.SITE.urls.threadJSON({ - boardID: this.boardID, - threadID: this.threadID, - }) - $.cleanCache((url) => url === api) - const that = this - $.cache(api, function () { - return that.fetchedPost(this, false) - }) - return - } - - // The post can be deleted by the time we check a quote. - if (this.archivedPost()) { - return - } - - $.addClass(this.root, 'warning') - this.root.textContent = `Post No.${this.postID} was not found.` - return + + const { posts } = response; + g.SITE.Build.spoilerRange[boardID] = posts[0].custom_spoiler; + + const foundPost = posts.find((p) => p.no === postID); + + if (!foundPost) { + this.handlePostNotFound(isCached); + return; } - - const board = g.boards[this.boardID] || new Board(this.boardID) - const thread = - g.threads.get(`${this.boardID}.${this.threadID}`) || - new Thread(this.threadID, board) - post = new Post( - g.SITE.Build.postFromObject(post, this.boardID), + + const board = g.boards[boardID] || new Board(boardID); + const threadKey = `${boardID}.${threadID}`; + const thread = g.threads.get(threadKey) || new Thread(threadID, board); + const newPost = new Post( + g.SITE.Build.postFromObject(foundPost, boardID), thread, board, { isFetchedQuote: true }, - ) - Main.callbackNodes('Post', [post]) - return this.insert(post) + ); + Main.callbackNodes("Post", [newPost]); + return this.insert(newPost); + } + + handleNon200Status(status, req) { + $.addClass(this.root, "warning"); + this.root.textContent = + status === 404 + ? `Thread No.${this.threadID} 404'd.` + : !status + ? "Connection Error" + : `Error ${req.statusText} (${req.status}).`; + + if (status && this.archivedPost()) { + return; + } + } + + handlePostNotFound(isCached) { + if (isCached) { + const api = g.SITE.urls.threadJSON({ + boardID: this.boardID, + threadID: this.threadID, + }); + $.cleanCache((url) => url === api); + $.cache(api, () => this.fetchedPost(this, false)); + return; + } + + if (this.archivedPost()) { + return; + } + + $.addClass(this.root, "warning"); + this.root.textContent = `Post No.${this.postID} was not found.`; } archivedPost() { diff --git a/src/classes/Post.ts b/src/classes/Post.ts index 08a64ea..d86a008 100644 --- a/src/classes/Post.ts +++ b/src/classes/Post.ts @@ -213,7 +213,7 @@ export default class Post { parseComment() { // Merge text nodes and remove empty ones. - let bq + let bq: HTMLElement this.nodes.comment.normalize() // Get the comment's text. @@ -221,7 +221,7 @@ export default class Post { // Remove: // 'Comment too long'... // EXIF data. (/p/) - this.nodes.commentClean = bq = this.nodes.comment.cloneNode(true) + this.nodes.commentClean = bq = this.nodes.comment.cloneNode(true) as HTMLElement g.SITE.cleanComment?.(bq) return (this.info.comment = this.nodesToText(bq)) } @@ -249,8 +249,8 @@ export default class Post { return this.nodesToText(bq) } - nodesToText(bq) { - let node + nodesToText(bq: HTMLElement) { + let node: Node let text = '' const nodes = $.X('.//br|.//text()', bq) let i = 0 @@ -260,7 +260,7 @@ export default class Post { return text } - cleanSpoilers(bq) { + cleanSpoilers(bq: HTMLElement) { const spoilers = $$(g.SITE.selectors.spoiler, bq) for (var node of spoilers) { $.replace(node, $.tn('[spoiler]')) @@ -274,7 +274,7 @@ export default class Post { } } - parseQuote(quotelink) { + parseQuote(quotelink: HTMLAnchorElement) { // Only add quotes that link to posts on an imageboard. // Don't add: // - board links. (>>>/b/) @@ -470,11 +470,11 @@ export class PostClone extends Post { static suffix = 0 - constructor(origin, context, contractThumb) { + constructor(origin: Post, context: any, contractThumb: boolean) { super() this.isClone = true - let file, fileRoots, key + let file: any, fileRoots: HTMLAnchorElement , key: string this.origin = origin this.context = context for (key of [ diff --git a/src/classes/ShimSet.js b/src/classes/ShimSet.js index 14fc0cc..0ddff27 100644 --- a/src/classes/ShimSet.js +++ b/src/classes/ShimSet.js @@ -3,6 +3,7 @@ * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md */ +import $ from '../platform/$' class ShimSet { constructor() { this.elements = $.dict() diff --git a/src/config/Config.js b/src/config/Config.js index 81d55c2..845da67 100644 --- a/src/config/Config.js +++ b/src/config/Config.js @@ -681,6 +681,7 @@ http://eye.swfchan.com/search/?q=%name;types:swf current-catalog-text:"Catalog" current-expired-text:"Expired" current-archive-text:"Archive"] +[ g pol ] [external-text:"FAQ","${meta.name}"]\ `, diff --git a/src/main/Main.js b/src/main/Main.js index 1853350..980675e 100644 --- a/src/main/Main.js +++ b/src/main/Main.js @@ -88,7 +88,6 @@ import Menu from '../Menu/Menu' import BoardConfig from '../General/BoardConfig' import CaptchaReplace from '../Posting/Captcha.replace' import Get from '../General/Get' -import Captcha from '../Posting/Captcha' import { dict, platform } from '../platform/helpers' import Polyfill from '../General/Polyfill' // import Test from "../General/Test"; diff --git a/src/meta/eventPage.js b/src/meta/eventPage.js index 262037f..751daf6 100644 --- a/src/meta/eventPage.js +++ b/src/meta/eventPage.js @@ -1,16 +1,15 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md - */ -let requestID = 0; chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { - const id = requestID; - requestID++; + const id = request; + request++; sendResponse(id); - return handlers[request.type](request, response => chrome.tabs.sendMessage(sender.tab.id, {id, data: response}));}); + const type = request.type; + if (handlers[type]) { + return handlers[type](request, response => chrome.tabs.sendMessage(sender.tab.id, {id, data: response})); + } else { + console.warn("Unknown request type", type); + return false; + }}); var handlers = { permission(request, cb) { diff --git a/src/platform/$.js b/src/platform/$.js index 664af24..a6f63b5 100644 --- a/src/platform/$.js +++ b/src/platform/$.js @@ -17,6 +17,7 @@ import { debounce, dict, MINUTE, platform, SECOND } from './helpers' const $ = (selector, root = document.body) => root.querySelector(selector) $.id = (id) => d.getElementById(id) +$.dict = dict $.ajaxPage = function (url, options) { if (options.responseType == null) { @@ -1252,6 +1253,7 @@ if (platform === 'crx') { } } + $.get = $.oneItemSugar((items, cb) => $.queueTask($.getSync, items, cb)) $.getSync = function (items, cb) { diff --git a/src/platform/CrossOrigin.js b/src/platform/CrossOrigin.js index a1a4b99..1f6ee3b 100644 --- a/src/platform/CrossOrigin.js +++ b/src/platform/CrossOrigin.js @@ -258,7 +258,16 @@ var CrossOrigin = { }, cache(url, cb) { - return $.cache(url, cb, { ajax: CrossOrigin.ajax }) + if (platform === 'userscript') { + return CrossOrigin.file(url, cb) + } + return eventPageRequest({ type: 'cache', url }, function (result) { + if (result) { + return cb(result) + } else { + return cb(null) + } + }) }, permission(cb, cbFail, origins) {